diff --git a/CHANGELOG.md b/CHANGELOG.md index 33481e118bf..f0b22c4e0dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +* Ref: Make hints Map instead of only Object (#1929) * Feat: Enable enableScopeSync by default for Android (#1928) ## 6.0.0-alpha.2 diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java b/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java index 50c206419bb..6d580b5430a 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java @@ -1,6 +1,7 @@ package io.sentry.android.core; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; +import static io.sentry.TypeCheckHint.ANDROID_ACTIVITY; import android.app.Activity; import android.app.ActivityManager; @@ -22,6 +23,7 @@ import java.io.Closeable; import java.io.IOException; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.WeakHashMap; @@ -123,7 +125,11 @@ private void addBreadcrumb(final @NotNull Activity activity, final @NotNull Stri breadcrumb.setData("screen", getActivityName(activity)); breadcrumb.setCategory("ui.lifecycle"); breadcrumb.setLevel(SentryLevel.INFO); - hub.addBreadcrumb(breadcrumb); + + final Map hintMap = new HashMap<>(); + hintMap.put(ANDROID_ACTIVITY, activity); + + hub.addBreadcrumb(breadcrumb, hintMap); } } diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/AppComponentsBreadcrumbsIntegration.java b/sentry-android-core/src/main/java/io/sentry/android/core/AppComponentsBreadcrumbsIntegration.java index 6e6538b1eb0..9536ef4b26c 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/AppComponentsBreadcrumbsIntegration.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/AppComponentsBreadcrumbsIntegration.java @@ -1,5 +1,7 @@ package io.sentry.android.core; +import static io.sentry.TypeCheckHint.ANDROID_CONFIGURATION; + import android.content.ComponentCallbacks2; import android.content.Context; import android.content.res.Configuration; @@ -13,7 +15,9 @@ import io.sentry.util.Objects; import java.io.Closeable; import java.io.IOException; +import java.util.HashMap; import java.util.Locale; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -95,7 +99,11 @@ public void onConfigurationChanged(@NotNull Configuration newConfig) { breadcrumb.setCategory("device.orientation"); breadcrumb.setData("position", orientation); breadcrumb.setLevel(SentryLevel.INFO); - hub.addBreadcrumb(breadcrumb); + + final Map hintMap = new HashMap<>(); + hintMap.put(ANDROID_CONFIGURATION, newConfig); + + hub.addBreadcrumb(breadcrumb, hintMap); } } diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java b/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java index 3b5539536bf..cd58637ac42 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/DefaultAndroidEventProcessor.java @@ -34,7 +34,7 @@ import io.sentry.protocol.SentryThread; import io.sentry.protocol.SentryTransaction; import io.sentry.protocol.User; -import io.sentry.util.ApplyScopeUtils; +import io.sentry.util.HintUtils; import io.sentry.util.Objects; import java.io.BufferedReader; import java.io.File; @@ -117,7 +117,7 @@ public DefaultAndroidEventProcessor( @Override public @NotNull SentryEvent process( - final @NotNull SentryEvent event, final @Nullable Object hint) { + final @NotNull SentryEvent event, final @Nullable Map hint) { final boolean applyScopeData = shouldApplyScopeData(event, hint); if (applyScopeData) { // we only set memory data if it's not a hard crash, when it's a hard crash the event is @@ -143,8 +143,8 @@ private void setCommons( } private boolean shouldApplyScopeData( - final @NotNull SentryBaseEvent event, final @Nullable Object hint) { - if (ApplyScopeUtils.shouldApplyScopeData(hint)) { + final @NotNull SentryBaseEvent event, final @Nullable Map hint) { + if (HintUtils.shouldApplyScopeData(hint)) { return true; } else { logger.log( @@ -888,7 +888,7 @@ private void setSideLoadedInfo(final @NotNull SentryBaseEvent event) { @Override public @NotNull SentryTransaction process( - final @NotNull SentryTransaction transaction, final @Nullable Object hint) { + final @NotNull SentryTransaction transaction, final @Nullable Map hint) { final boolean applyScopeData = shouldApplyScopeData(transaction, hint); if (applyScopeData) { diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/EnvelopeFileObserver.java b/sentry-android-core/src/main/java/io/sentry/android/core/EnvelopeFileObserver.java index 2715af6f1a0..57cadbcdd56 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/EnvelopeFileObserver.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/EnvelopeFileObserver.java @@ -1,6 +1,7 @@ package io.sentry.android.core; import static io.sentry.SentryLevel.ERROR; +import static io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT; import android.os.FileObserver; import io.sentry.IEnvelopeSender; @@ -14,6 +15,8 @@ import io.sentry.hints.SubmissionResult; import io.sentry.util.Objects; import java.io.File; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.jetbrains.annotations.NotNull; @@ -56,7 +59,11 @@ public void onEvent(int eventType, @Nullable String relativePath) { // TODO: Only some event types should be pass through? final CachedEnvelopeHint hint = new CachedEnvelopeHint(flushTimeoutMillis, logger); - envelopeSender.processEnvelopeFile(this.rootPath + File.separator + relativePath, hint); + + final Map hintMap = new HashMap<>(); + hintMap.put(SENTRY_TYPE_CHECK_HINT, hint); + + envelopeSender.processEnvelopeFile(this.rootPath + File.separator + relativePath, hintMap); } private static final class CachedEnvelopeHint diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/PerformanceAndroidEventProcessor.java b/sentry-android-core/src/main/java/io/sentry/android/core/PerformanceAndroidEventProcessor.java index 6bd7651ff9f..708d5ecd936 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/PerformanceAndroidEventProcessor.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/PerformanceAndroidEventProcessor.java @@ -42,7 +42,7 @@ final class PerformanceAndroidEventProcessor implements EventProcessor { */ @Override @Nullable - public SentryEvent process(@NotNull SentryEvent event, @Nullable Object hint) { + public SentryEvent process(@NotNull SentryEvent event, @Nullable Map hint) { // that's only necessary because on newer versions of Unity, if not overriding this method, it's // throwing 'java.lang.AbstractMethodError: abstract method' and the reason is probably // compilation mismatch. @@ -52,7 +52,7 @@ public SentryEvent process(@NotNull SentryEvent event, @Nullable Object hint) { @SuppressWarnings("NullAway") @Override public synchronized @NotNull SentryTransaction process( - @NotNull SentryTransaction transaction, @Nullable Object hint) { + @NotNull SentryTransaction transaction, @Nullable Map hint) { if (!options.isTracingEnabled()) { return transaction; diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegration.java b/sentry-android-core/src/main/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegration.java index 21c0d0e1922..c626debf41d 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegration.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegration.java @@ -30,6 +30,7 @@ import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_TIMEZONE_CHANGED; import static android.content.Intent.ACTION_TIME_CHANGED; +import static io.sentry.TypeCheckHint.ANDROID_INTENT; import android.content.BroadcastReceiver; import android.content.Context; @@ -213,7 +214,11 @@ public void onReceive(Context context, Intent intent) { breadcrumb.setData("extras", newExtras); } breadcrumb.setLevel(SentryLevel.INFO); - hub.addBreadcrumb(breadcrumb); + + final Map hintMap = new HashMap<>(); + hintMap.put(ANDROID_INTENT, intent); + + hub.addBreadcrumb(breadcrumb, hintMap); } } } diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/TempSensorBreadcrumbsIntegration.java b/sentry-android-core/src/main/java/io/sentry/android/core/TempSensorBreadcrumbsIntegration.java index 94373d9bcc1..0d8877a4077 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/TempSensorBreadcrumbsIntegration.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/TempSensorBreadcrumbsIntegration.java @@ -1,6 +1,7 @@ package io.sentry.android.core; import static android.content.Context.SENSOR_SERVICE; +import static io.sentry.TypeCheckHint.ANDROID_SENSOR_EVENT; import android.content.Context; import android.hardware.Sensor; @@ -15,6 +16,8 @@ import io.sentry.util.Objects; import java.io.Closeable; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; @@ -103,7 +106,11 @@ public void onSensorChanged(final @NotNull SensorEvent event) { breadcrumb.setData("timestamp", event.timestamp); breadcrumb.setLevel(SentryLevel.INFO); breadcrumb.setData("degree", event.values[0]); // Celsius - hub.addBreadcrumb(breadcrumb); + + final Map hintMap = new HashMap<>(); + hintMap.put(ANDROID_SENSOR_EVENT, event); + + hub.addBreadcrumb(breadcrumb, hintMap); } } diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java b/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java index 9fa3ecb7a38..4b65114ae52 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/internal/gestures/SentryGestureListener.java @@ -1,5 +1,8 @@ package io.sentry.android.core.internal.gestures; +import static io.sentry.TypeCheckHint.ANDROID_MOTION_EVENT; +import static io.sentry.TypeCheckHint.ANDROID_VIEW; + import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; @@ -10,6 +13,7 @@ import io.sentry.android.core.SentryAndroidOptions; import java.lang.ref.WeakReference; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -51,7 +55,11 @@ public void onUp(final @NotNull MotionEvent motionEvent) { } final String direction = scrollState.calculateDirection(motionEvent); - addBreadcrumb(scrollTarget, scrollState.type, Collections.singletonMap("direction", direction)); + addBreadcrumb( + scrollTarget, + scrollState.type, + Collections.singletonMap("direction", direction), + motionEvent); scrollState.reset(); } @@ -88,7 +96,7 @@ public boolean onSingleTapUp(final @Nullable MotionEvent motionEvent) { return false; } - addBreadcrumb(target, "click", Collections.emptyMap()); + addBreadcrumb(target, "click", Collections.emptyMap(), motionEvent); return false; } @@ -154,7 +162,8 @@ public void onLongPress(MotionEvent motionEvent) {} private void addBreadcrumb( final @NotNull View target, final @NotNull String eventType, - final @NotNull Map additionalData) { + final @NotNull Map additionalData, + final @NotNull MotionEvent motionEvent) { @NotNull String className; @Nullable String canonicalName = target.getClass().getCanonicalName(); if (canonicalName != null) { @@ -163,9 +172,14 @@ private void addBreadcrumb( className = target.getClass().getSimpleName(); } + final Map hintMap = new HashMap<>(); + hintMap.put(ANDROID_MOTION_EVENT, motionEvent); + hintMap.put(ANDROID_VIEW, target); + hub.addBreadcrumb( Breadcrumb.userInteraction( - eventType, ViewUtils.getResourceId(target), className, additionalData)); + eventType, ViewUtils.getResourceId(target), className, additionalData), + hintMap); } private @Nullable View ensureWindowDecorView(final @NotNull String caller) { diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt index 6a5c88ef5aa..33d9286f909 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt @@ -20,6 +20,7 @@ import io.sentry.SentryLevel import io.sentry.SentryOptions import io.sentry.SentryTracer import io.sentry.SpanStatus +import io.sentry.TraceState import io.sentry.TransactionContext import io.sentry.TransactionFinishedCallback import java.util.Date @@ -160,7 +161,8 @@ class ActivityLifecycleIntegrationTest { assertEquals("navigation", it.type) assertEquals(SentryLevel.INFO, it.level) // cant assert data, its not a public API - } + }, + anyOrNull() ) } @@ -172,7 +174,7 @@ class ActivityLifecycleIntegrationTest { val activity = mock() sut.onActivityCreated(activity, fixture.bundle) - verify(fixture.hub).addBreadcrumb(any()) + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) } @Test @@ -183,7 +185,7 @@ class ActivityLifecycleIntegrationTest { val activity = mock() sut.onActivityStarted(activity) - verify(fixture.hub).addBreadcrumb(any()) + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) } @Test @@ -194,7 +196,7 @@ class ActivityLifecycleIntegrationTest { val activity = mock() sut.onActivityResumed(activity) - verify(fixture.hub).addBreadcrumb(any()) + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) } @Test @@ -205,7 +207,7 @@ class ActivityLifecycleIntegrationTest { val activity = mock() sut.onActivityPaused(activity) - verify(fixture.hub).addBreadcrumb(any()) + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) } @Test @@ -216,7 +218,7 @@ class ActivityLifecycleIntegrationTest { val activity = mock() sut.onActivityStopped(activity) - verify(fixture.hub).addBreadcrumb(any()) + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) } @Test @@ -227,7 +229,7 @@ class ActivityLifecycleIntegrationTest { val activity = mock() sut.onActivitySaveInstanceState(activity, fixture.bundle) - verify(fixture.hub).addBreadcrumb(any()) + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) } @Test @@ -238,7 +240,7 @@ class ActivityLifecycleIntegrationTest { val activity = mock() sut.onActivityDestroyed(activity) - verify(fixture.hub).addBreadcrumb(any()) + verify(fixture.hub).addBreadcrumb(any(), anyOrNull()) } @Test @@ -370,7 +372,7 @@ class ActivityLifecycleIntegrationTest { check { assertEquals(SpanStatus.OK, it.status) }, - anyOrNull() + anyOrNull() ) } @@ -391,7 +393,7 @@ class ActivityLifecycleIntegrationTest { check { assertEquals(SpanStatus.UNKNOWN_ERROR, it.status) }, - anyOrNull() + anyOrNull() ) } @@ -406,7 +408,7 @@ class ActivityLifecycleIntegrationTest { sut.onActivityCreated(activity, fixture.bundle) sut.onActivityPostResumed(activity) - verify(fixture.hub, never()).captureTransaction(any(), anyOrNull()) + verify(fixture.hub, never()).captureTransaction(any(), anyOrNull()) } @Test @@ -417,7 +419,7 @@ class ActivityLifecycleIntegrationTest { val activity = mock() sut.onActivityPostResumed(activity) - verify(fixture.hub, never()).captureTransaction(any(), anyOrNull()) + verify(fixture.hub, never()).captureTransaction(any(), anyOrNull()) } @Test @@ -430,7 +432,7 @@ class ActivityLifecycleIntegrationTest { sut.onActivityCreated(activity, fixture.bundle) sut.onActivityDestroyed(activity) - verify(fixture.hub).captureTransaction(any(), anyOrNull()) + verify(fixture.hub).captureTransaction(any(), anyOrNull()) } @Test @@ -499,7 +501,7 @@ class ActivityLifecycleIntegrationTest { sut.onActivityCreated(mock(), mock()) sut.onActivityCreated(mock(), fixture.bundle) - verify(fixture.hub).captureTransaction(any(), anyOrNull()) + verify(fixture.hub).captureTransaction(any(), anyOrNull()) } @Test @@ -512,7 +514,7 @@ class ActivityLifecycleIntegrationTest { sut.onActivityCreated(activity, mock()) sut.onActivityResumed(activity) - verify(fixture.hub, never()).captureTransaction(any(), any()) + verify(fixture.hub, never()).captureTransaction(any(), any()) } @Test @@ -539,7 +541,7 @@ class ActivityLifecycleIntegrationTest { sut.onActivityCreated(activity, mock()) sut.onActivityResumed(activity) - verify(fixture.hub).captureTransaction(any(), anyOrNull()) + verify(fixture.hub).captureTransaction(any(), anyOrNull()) } @Test diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/AppComponentsBreadcrumbsIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/AppComponentsBreadcrumbsIntegrationTest.kt index aa6adc2971a..70ee62d905c 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/AppComponentsBreadcrumbsIntegrationTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/AppComponentsBreadcrumbsIntegrationTest.kt @@ -5,6 +5,7 @@ import android.content.Context import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.check import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.never @@ -139,7 +140,8 @@ class AppComponentsBreadcrumbsIntegrationTest { assertEquals("navigation", it.type) assertEquals(SentryLevel.INFO, it.level) // cant assert data, its not a public API - } + }, + anyOrNull() ) } } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/DefaultAndroidEventProcessorTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/DefaultAndroidEventProcessorTest.kt index 904a2c6f1ea..5c82a54fded 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/DefaultAndroidEventProcessorTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/DefaultAndroidEventProcessorTest.kt @@ -16,6 +16,7 @@ import io.sentry.SentryLevel import io.sentry.SentryOptions import io.sentry.SentryTracer import io.sentry.TransactionContext +import io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT import io.sentry.android.core.DefaultAndroidEventProcessor.EMULATOR import io.sentry.android.core.DefaultAndroidEventProcessor.KERNEL_VERSION import io.sentry.android.core.DefaultAndroidEventProcessor.ROOTED @@ -162,7 +163,8 @@ class DefaultAndroidEventProcessorTest { fun `When Event and hint is Cached, data should not be applied`() { val sut = fixture.getSut(context) - assertNotNull(sut.process(SentryEvent(), CachedEvent())) { + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CachedEvent()) + assertNotNull(sut.process(SentryEvent(), hintsMap)) { assertNull(it.contexts.app) assertNull(it.debugMeta) assertNull(it.dist) @@ -173,7 +175,8 @@ class DefaultAndroidEventProcessorTest { fun `When Transaction and hint is Cached, data should not be applied`() { val sut = fixture.getSut(context) - assertNotNull(sut.process(SentryTransaction(fixture.sentryTracer), CachedEvent())) { + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CachedEvent()) + assertNotNull(sut.process(SentryTransaction(fixture.sentryTracer), hintsMap)) { assertNull(it.contexts.app) assertNull(it.dist) } @@ -183,7 +186,8 @@ class DefaultAndroidEventProcessorTest { fun `When Event and hint is Cached, userId is applied anyway`() { val sut = fixture.getSut(context) - assertNotNull(sut.process(SentryEvent(), CachedEvent())) { + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CachedEvent()) + assertNotNull(sut.process(SentryEvent(), hintsMap)) { assertNotNull(it.user) } } @@ -192,7 +196,8 @@ class DefaultAndroidEventProcessorTest { fun `When Transaction and hint is Cached, userId is applied anyway`() { val sut = fixture.getSut(context) - assertNotNull(sut.process(SentryTransaction(fixture.sentryTracer), CachedEvent())) { + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CachedEvent()) + assertNotNull(sut.process(SentryTransaction(fixture.sentryTracer), hintsMap)) { assertNotNull(it.user) } } @@ -254,7 +259,8 @@ class DefaultAndroidEventProcessorTest { fun `Processor won't throw exception when theres a hint`() { val processor = DefaultAndroidEventProcessor(context, fixture.options.logger, fixture.buildInfo, mock()) - processor.process(SentryEvent(), CachedEvent()) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CachedEvent()) + processor.process(SentryEvent(), hintsMap) verify((fixture.options.logger as DiagnosticLogger).logger, never())!!.log(eq(SentryLevel.ERROR), any(), any()) } @@ -306,7 +312,8 @@ class DefaultAndroidEventProcessorTest { fun `When hint is Cached, memory data should not be applied`() { val sut = fixture.getSut(context) - assertNotNull(sut.process(SentryEvent(), CachedEvent())) { + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CachedEvent()) + assertNotNull(sut.process(SentryEvent(), hintsMap)) { assertNull(it.contexts.device!!.freeMemory) assertNull(it.contexts.device!!.isLowMemory) } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/EnvelopeFileObserverTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/EnvelopeFileObserverTest.kt index 1d25cb60800..6a71706d1ce 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/EnvelopeFileObserverTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/EnvelopeFileObserverTest.kt @@ -15,6 +15,7 @@ import io.sentry.hints.ApplyScopeData import io.sentry.hints.Resettable import io.sentry.hints.Retryable import io.sentry.hints.SubmissionResult +import io.sentry.util.HintUtils import org.junit.runner.RunWith import java.io.File import kotlin.test.Test @@ -94,13 +95,14 @@ class EnvelopeFileObserverTest { verify(fixture.envelopeSender).processEnvelopeFile( eq(fixture.path + File.separator + fixture.fileName), check { - (it as SubmissionResult).setResult(true) - (it as Retryable).isRetry = true + val hint = HintUtils.getSentrySdkHint(it) + (hint as SubmissionResult).setResult(true) + (hint as Retryable).isRetry = true - (it as Resettable).reset() + (hint as Resettable).reset() - assertFalse(it.isRetry) - assertFalse(it.isSuccess) + assertFalse(hint.isRetry) + assertFalse(hint.isSuccess) } ) } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegrationTest.kt index f8f060045a3..ca4a34f358b 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegrationTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/SystemEventsBreadcrumbsIntegrationTest.kt @@ -3,6 +3,7 @@ package io.sentry.android.core import android.content.Context import android.content.Intent import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.check import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.never @@ -73,7 +74,7 @@ class SystemEventsBreadcrumbsIntegrationTest { val intent = Intent().apply { action = Intent.ACTION_TIME_CHANGED } - sut.receiver!!.onReceive(any(), intent) + sut.receiver!!.onReceive(fixture.context, intent) verify(fixture.hub).addBreadcrumb( check { @@ -81,7 +82,8 @@ class SystemEventsBreadcrumbsIntegrationTest { assertEquals("system", it.type) assertEquals(SentryLevel.INFO, it.level) // cant assert data, its not a public API - } + }, + anyOrNull() ) } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerClickTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerClickTest.kt index 5bafe1b6cff..8c99c96c666 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerClickTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerClickTest.kt @@ -9,6 +9,7 @@ import android.view.Window import android.widget.CheckBox import android.widget.RadioButton import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.check import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.never @@ -113,7 +114,8 @@ class SentryGestureListenerClickTest { assertEquals("test_button", it.data["view.id"]) assertEquals("android.view.View", it.data["view.class"]) assertEquals(INFO, it.level) - } + }, + anyOrNull() ) } @@ -132,7 +134,8 @@ class SentryGestureListenerClickTest { check { assertEquals("radio_button", it.data["view.id"]) assertEquals("android.widget.RadioButton", it.data["view.class"]) - } + }, + anyOrNull() ) } @@ -151,7 +154,8 @@ class SentryGestureListenerClickTest { check { assertEquals("check_box", it.data["view.id"]) assertEquals("android.widget.CheckBox", it.data["view.class"]) - } + }, + anyOrNull() ) } @@ -182,7 +186,8 @@ class SentryGestureListenerClickTest { check { assertEquals(decorView.javaClass.canonicalName, it.data["view.class"]) assertEquals("decor_view", it.data["view.id"]) - } + }, + anyOrNull() ) } @@ -212,7 +217,8 @@ class SentryGestureListenerClickTest { verify(fixture.hub).addBreadcrumb( check { assertEquals(fixture.target.javaClass.simpleName, it.data["view.class"]) - } + }, + anyOrNull() ) } } diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerScrollTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerScrollTest.kt index 690a0da5e08..91354e7a588 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerScrollTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/internal/gestures/SentryGestureListenerScrollTest.kt @@ -10,6 +10,7 @@ import android.widget.AbsListView import android.widget.ListAdapter import androidx.core.view.ScrollingView import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.check import com.nhaarman.mockitokotlin2.inOrder import com.nhaarman.mockitokotlin2.mock @@ -92,7 +93,8 @@ class SentryGestureListenerScrollTest { assertEquals(fixture.target.javaClass.canonicalName, it.data["view.class"]) assertEquals("left", it.data["direction"]) assertEquals(INFO, it.level) - } + }, + anyOrNull() ) } @@ -136,7 +138,8 @@ class SentryGestureListenerScrollTest { assertEquals(fixture.target.javaClass.canonicalName, it.data["view.class"]) assertEquals("down", it.data["direction"]) assertEquals(INFO, it.level) - } + }, + anyOrNull() ) verify(fixture.hub).addBreadcrumb( check { @@ -146,7 +149,8 @@ class SentryGestureListenerScrollTest { assertEquals(fixture.target.javaClass.canonicalName, it.data["view.class"]) assertEquals("up", it.data["direction"]) assertEquals(INFO, it.level) - } + }, + anyOrNull() ) } verifyNoMoreInteractions(fixture.hub) diff --git a/sentry-android-fragment/src/main/java/io/sentry/android/fragment/SentryFragmentLifecycleCallbacks.kt b/sentry-android-fragment/src/main/java/io/sentry/android/fragment/SentryFragmentLifecycleCallbacks.kt index 9b620f3f774..6db16485eb0 100644 --- a/sentry-android-fragment/src/main/java/io/sentry/android/fragment/SentryFragmentLifecycleCallbacks.kt +++ b/sentry-android-fragment/src/main/java/io/sentry/android/fragment/SentryFragmentLifecycleCallbacks.kt @@ -12,6 +12,7 @@ import io.sentry.IHub import io.sentry.ISpan import io.sentry.SentryLevel.INFO import io.sentry.SpanStatus +import io.sentry.TypeCheckHint.ANDROID_FRAGMENT import java.util.WeakHashMap @Suppress("TooManyFunctions") @@ -116,7 +117,10 @@ class SentryFragmentLifecycleCallbacks( category = "ui.fragment.lifecycle" level = INFO } - hub.addBreadcrumb(breadcrumb) + + val hintsMap = mutableMapOf(ANDROID_FRAGMENT to fragment) + + hub.addBreadcrumb(breadcrumb, hintsMap) } private fun getFragmentName(fragment: Fragment): String { diff --git a/sentry-android-fragment/src/test/java/io/sentry/android/fragment/SentryFragmentLifecycleCallbacksTest.kt b/sentry-android-fragment/src/test/java/io/sentry/android/fragment/SentryFragmentLifecycleCallbacksTest.kt index b07e5922553..a2b57206335 100644 --- a/sentry-android-fragment/src/test/java/io/sentry/android/fragment/SentryFragmentLifecycleCallbacksTest.kt +++ b/sentry-android-fragment/src/test/java/io/sentry/android/fragment/SentryFragmentLifecycleCallbacksTest.kt @@ -5,6 +5,7 @@ import android.os.Bundle import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.check import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.never @@ -268,7 +269,8 @@ class SentryFragmentLifecycleCallbacksTest { assertEquals(INFO, breadcrumb.level) assertEquals(expectedState, breadcrumb.getData("state")) assertEquals(fixture.fragment.javaClass.simpleName, breadcrumb.getData("screen")) - } + }, + anyOrNull() ) } } diff --git a/sentry-android-okhttp/src/main/java/io/sentry/android/okhttp/SentryOkHttpInterceptor.kt b/sentry-android-okhttp/src/main/java/io/sentry/android/okhttp/SentryOkHttpInterceptor.kt index c9eb52acd73..041796fba39 100644 --- a/sentry-android-okhttp/src/main/java/io/sentry/android/okhttp/SentryOkHttpInterceptor.kt +++ b/sentry-android-okhttp/src/main/java/io/sentry/android/okhttp/SentryOkHttpInterceptor.kt @@ -6,6 +6,8 @@ import io.sentry.IHub import io.sentry.ISpan import io.sentry.SpanStatus import io.sentry.TracingOrigins +import io.sentry.TypeCheckHint.OKHTTP_REQUEST +import io.sentry.TypeCheckHint.OKHTTP_RESPONSE import okhttp3.Interceptor import okhttp3.Request import okhttp3.Response @@ -59,10 +61,17 @@ class SentryOkHttpInterceptor( request.body?.contentLength().ifHasValidLength { breadcrumb.setData("request_body_size", it) } - response?.body?.contentLength().ifHasValidLength { - breadcrumb.setData("response_body_size", it) + + val hintsMap = mutableMapOf(OKHTTP_REQUEST to request) + response?.let { + it.body?.contentLength().ifHasValidLength { responseBodySize -> + breadcrumb.setData("response_body_size", responseBodySize) + } + + hintsMap[OKHTTP_RESPONSE] = it } - hub.addBreadcrumb(breadcrumb) + + hub.addBreadcrumb(breadcrumb, hintsMap) } } diff --git a/sentry-android-okhttp/src/test/java/io/sentry/android/okhttp/SentryOkHttpInterceptorTest.kt b/sentry-android-okhttp/src/test/java/io/sentry/android/okhttp/SentryOkHttpInterceptorTest.kt index c312b1f486e..65b39b746e8 100644 --- a/sentry-android-okhttp/src/test/java/io/sentry/android/okhttp/SentryOkHttpInterceptorTest.kt +++ b/sentry-android-okhttp/src/test/java/io/sentry/android/okhttp/SentryOkHttpInterceptorTest.kt @@ -2,6 +2,7 @@ package io.sentry.android.okhttp import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.check import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.verify @@ -162,7 +163,8 @@ class SentryOkHttpInterceptorTest { assertEquals("http", it.type) assertEquals(13L, it.data["response_body_size"]) assertEquals(12L, it.data["request_body_size"]) - } + }, + anyOrNull() ) } @@ -182,7 +184,8 @@ class SentryOkHttpInterceptorTest { verify(fixture.hub).addBreadcrumb( check { assertEquals("http", it.type) - } + }, + anyOrNull() ) } diff --git a/sentry-android-timber/src/main/java/io/sentry/android/timber/SentryTimberTree.kt b/sentry-android-timber/src/main/java/io/sentry/android/timber/SentryTimberTree.kt index 282573647c5..da0b7740acd 100644 --- a/sentry-android-timber/src/main/java/io/sentry/android/timber/SentryTimberTree.kt +++ b/sentry-android-timber/src/main/java/io/sentry/android/timber/SentryTimberTree.kt @@ -200,7 +200,7 @@ class SentryTimberTree( val sentryMessage = Message().apply { this.message = message if (!message.isNullOrEmpty() && args.isNotEmpty()) { - this.formatted = message?.format(*args) + this.formatted = message.format(*args) } this.params = args.map { it.toString() } } diff --git a/sentry-apache-http-client-5/api/sentry-apache-http-client-5.api b/sentry-apache-http-client-5/api/sentry-apache-http-client-5.api index b911ea86a2e..8c27b45c821 100644 --- a/sentry-apache-http-client-5/api/sentry-apache-http-client-5.api +++ b/sentry-apache-http-client-5/api/sentry-apache-http-client-5.api @@ -2,7 +2,7 @@ public final class io/sentry/transport/apache/ApacheHttpClientTransport : io/sen public fun (Lio/sentry/SentryOptions;Lio/sentry/RequestDetails;Lorg/apache/hc/client5/http/impl/async/CloseableHttpAsyncClient;Lio/sentry/transport/RateLimiter;)V public fun close ()V public fun flush (J)V - public fun send (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)V + public fun send (Lio/sentry/SentryEnvelope;Ljava/util/Map;)V } public final class io/sentry/transport/apache/ApacheHttpClientTransportFactory : io/sentry/ITransportFactory { diff --git a/sentry-apache-http-client-5/src/main/java/io/sentry/transport/apache/ApacheHttpClientTransport.java b/sentry-apache-http-client-5/src/main/java/io/sentry/transport/apache/ApacheHttpClientTransport.java index a2a52581433..2a161577a33 100644 --- a/sentry-apache-http-client-5/src/main/java/io/sentry/transport/apache/ApacheHttpClientTransport.java +++ b/sentry-apache-http-client-5/src/main/java/io/sentry/transport/apache/ApacheHttpClientTransport.java @@ -9,6 +9,7 @@ import io.sentry.transport.ITransport; import io.sentry.transport.RateLimiter; import io.sentry.transport.ReusableCountLatch; +import io.sentry.util.HintUtils; import io.sentry.util.Objects; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -63,10 +64,11 @@ public ApacheHttpClientTransport( @Override @SuppressWarnings("FutureReturnValueIgnored") - public void send(final @NotNull SentryEnvelope envelope, final @Nullable Object hint) + public void send(final @NotNull SentryEnvelope envelope, final @Nullable Map hint) throws IOException { if (isSchedulingAllowed()) { - final SentryEnvelope filteredEnvelope = rateLimiter.filter(envelope, hint); + Object sentrySdkHint = HintUtils.getSentrySdkHint(hint); + final SentryEnvelope filteredEnvelope = rateLimiter.filter(envelope, sentrySdkHint); if (filteredEnvelope != null) { currentlyRunning.increment(); diff --git a/sentry-apollo/src/main/java/io/sentry/apollo/SentryApolloInterceptor.kt b/sentry-apollo/src/main/java/io/sentry/apollo/SentryApolloInterceptor.kt index c515da01546..d0f53c62916 100644 --- a/sentry-apollo/src/main/java/io/sentry/apollo/SentryApolloInterceptor.kt +++ b/sentry-apollo/src/main/java/io/sentry/apollo/SentryApolloInterceptor.kt @@ -17,6 +17,8 @@ import io.sentry.IHub import io.sentry.ISpan import io.sentry.SentryLevel import io.sentry.SpanStatus +import io.sentry.TypeCheckHint.APOLLO_REQUEST +import io.sentry.TypeCheckHint.APOLLO_RESPONSE import java.util.concurrent.Executor class SentryApolloInterceptor( @@ -112,7 +114,9 @@ class SentryApolloInterceptor( httpResponse.body()?.contentLength().ifHasValidLength { contentLength -> breadcrumb.setData("response_body_size", contentLength) } - hub.addBreadcrumb(breadcrumb) + + val hintsMap = mutableMapOf(APOLLO_REQUEST to httpRequest, APOLLO_RESPONSE to httpResponse) + hub.addBreadcrumb(breadcrumb, hintsMap) } } } diff --git a/sentry-apollo/src/test/java/io/sentry/apollo/SentryApolloInterceptorTest.kt b/sentry-apollo/src/test/java/io/sentry/apollo/SentryApolloInterceptorTest.kt index 645f9bba307..7dac9ac84da 100644 --- a/sentry-apollo/src/test/java/io/sentry/apollo/SentryApolloInterceptorTest.kt +++ b/sentry-apollo/src/test/java/io/sentry/apollo/SentryApolloInterceptorTest.kt @@ -15,6 +15,7 @@ import io.sentry.SentryOptions import io.sentry.SentryTraceHeader import io.sentry.SentryTracer import io.sentry.SpanStatus +import io.sentry.TraceState import io.sentry.TransactionContext import io.sentry.protocol.SentryTransaction import kotlinx.coroutines.launch @@ -84,7 +85,7 @@ class SentryApolloInterceptorTest { assertTransactionDetails(it) assertEquals(SpanStatus.OK, it.spans.first().status) }, - anyOrNull() + anyOrNull() ) } @@ -97,7 +98,7 @@ class SentryApolloInterceptorTest { assertTransactionDetails(it) assertEquals(SpanStatus.PERMISSION_DENIED, it.spans.first().status) }, - anyOrNull() + anyOrNull() ) } @@ -110,7 +111,7 @@ class SentryApolloInterceptorTest { assertTransactionDetails(it) assertEquals(SpanStatus.INTERNAL_ERROR, it.spans.first().status) }, - anyOrNull() + anyOrNull() ) } @@ -144,7 +145,7 @@ class SentryApolloInterceptorTest { val httpClientSpan = it.spans.first() assertEquals("overwritten description", httpClientSpan.description) }, - anyOrNull() + anyOrNull() ) } @@ -158,7 +159,7 @@ class SentryApolloInterceptorTest { check { assertEquals(1, it.spans.size) }, - anyOrNull() + anyOrNull() ) } @@ -170,7 +171,8 @@ class SentryApolloInterceptorTest { assertEquals("http", it.type) assertEquals(280L, it.data["response_body_size"]) assertEquals(193L, it.data["request_body_size"]) - } + }, + anyOrNull() ) } diff --git a/sentry-graphql/src/main/java/io/sentry/graphql/SentryDataFetcherExceptionHandler.java b/sentry-graphql/src/main/java/io/sentry/graphql/SentryDataFetcherExceptionHandler.java index b07fbebae3a..d0f64a14429 100644 --- a/sentry-graphql/src/main/java/io/sentry/graphql/SentryDataFetcherExceptionHandler.java +++ b/sentry-graphql/src/main/java/io/sentry/graphql/SentryDataFetcherExceptionHandler.java @@ -1,11 +1,15 @@ package io.sentry.graphql; +import static io.sentry.TypeCheckHint.GRAPHQL_HANDLER_PARAMETERS; + import graphql.execution.DataFetcherExceptionHandler; import graphql.execution.DataFetcherExceptionHandlerParameters; import graphql.execution.DataFetcherExceptionHandlerResult; import io.sentry.HubAdapter; import io.sentry.IHub; import io.sentry.util.Objects; +import java.util.HashMap; +import java.util.Map; import org.jetbrains.annotations.NotNull; /** @@ -30,7 +34,10 @@ public SentryDataFetcherExceptionHandler(final @NotNull DataFetcherExceptionHand @SuppressWarnings("deprecation") public DataFetcherExceptionHandlerResult onException( final @NotNull DataFetcherExceptionHandlerParameters handlerParameters) { - hub.captureException(handlerParameters.getException(), handlerParameters); + final Map hintMap = new HashMap<>(); + hintMap.put(GRAPHQL_HANDLER_PARAMETERS, handlerParameters); + + hub.captureException(handlerParameters.getException(), hintMap); return delegate.onException(handlerParameters); } } diff --git a/sentry-graphql/src/test/kotlin/io/sentry/graphql/SentryDataFetcherExceptionHandlerTest.kt b/sentry-graphql/src/test/kotlin/io/sentry/graphql/SentryDataFetcherExceptionHandlerTest.kt index cc1db48e522..ca98debaeb8 100644 --- a/sentry-graphql/src/test/kotlin/io/sentry/graphql/SentryDataFetcherExceptionHandlerTest.kt +++ b/sentry-graphql/src/test/kotlin/io/sentry/graphql/SentryDataFetcherExceptionHandlerTest.kt @@ -1,5 +1,7 @@ package io.sentry.graphql +import com.nhaarman.mockitokotlin2.anyOrNull +import com.nhaarman.mockitokotlin2.eq import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.verify import graphql.execution.DataFetcherExceptionHandler @@ -19,7 +21,7 @@ class SentryDataFetcherExceptionHandlerTest { val parameters = DataFetcherExceptionHandlerParameters.newExceptionParameters().exception(exception).build() handler.onException(parameters) - verify(hub).captureException(exception, parameters) + verify(hub).captureException(eq(exception), anyOrNull()) verify(delegate).onException(parameters) } } 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 2796dd39c5b..bb8ee6672f8 100644 --- a/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java +++ b/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java @@ -1,5 +1,8 @@ package io.sentry.jul; +import static io.sentry.TypeCheckHint.JUL_LOG_RECORD; +import static io.sentry.TypeCheckHint.SENTRY_SYNTHETIC_EXCEPTION; + import com.jakewharton.nopen.annotation.Open; import io.sentry.Breadcrumb; import io.sentry.Sentry; @@ -12,6 +15,7 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.ErrorManager; @@ -75,10 +79,16 @@ public void publish(final @NotNull LogRecord record) { } try { if (record.getLevel().intValue() >= minimumEventLevel.intValue()) { - Sentry.captureEvent(createEvent(record)); + final Map hintMap = new HashMap<>(); + hintMap.put(SENTRY_SYNTHETIC_EXCEPTION, record); + + Sentry.captureEvent(createEvent(record), hintMap); } if (record.getLevel().intValue() >= minimumBreadcrumbLevel.intValue()) { - Sentry.addBreadcrumb(createBreadcrumb(record)); + final Map hintMap = new HashMap<>(); + hintMap.put(JUL_LOG_RECORD, record); + + Sentry.addBreadcrumb(createBreadcrumb(record), hintMap); } } catch (RuntimeException e) { reportError( diff --git a/sentry-log4j2/src/main/java/io/sentry/log4j2/SentryAppender.java b/sentry-log4j2/src/main/java/io/sentry/log4j2/SentryAppender.java index f2aaaeddfe1..3e4390532d4 100644 --- a/sentry-log4j2/src/main/java/io/sentry/log4j2/SentryAppender.java +++ b/sentry-log4j2/src/main/java/io/sentry/log4j2/SentryAppender.java @@ -1,5 +1,8 @@ package io.sentry.log4j2; +import static io.sentry.TypeCheckHint.LOG4J_LOG_EVENT; +import static io.sentry.TypeCheckHint.SENTRY_SYNTHETIC_EXCEPTION; + import com.jakewharton.nopen.annotation.Open; import io.sentry.Breadcrumb; import io.sentry.DateUtils; @@ -15,6 +18,7 @@ import io.sentry.util.CollectionUtils; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -125,10 +129,16 @@ public void start() { @Override public void append(final @NotNull LogEvent eventObject) { if (eventObject.getLevel().isMoreSpecificThan(minimumEventLevel)) { - hub.captureEvent(createEvent(eventObject)); + final Map hintMap = new HashMap<>(); + hintMap.put(SENTRY_SYNTHETIC_EXCEPTION, eventObject); + + hub.captureEvent(createEvent(eventObject), hintMap); } if (eventObject.getLevel().isMoreSpecificThan(minimumBreadcrumbLevel)) { - hub.addBreadcrumb(createBreadcrumb(eventObject)); + final Map hintMap = new HashMap<>(); + hintMap.put(LOG4J_LOG_EVENT, eventObject); + + hub.addBreadcrumb(createBreadcrumb(eventObject), hintMap); } } 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 db6c2086b06..a7d6a321029 100644 --- a/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java +++ b/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java @@ -1,5 +1,8 @@ package io.sentry.logback; +import static io.sentry.TypeCheckHint.LOGBACK_LOGGING_EVENT; +import static io.sentry.TypeCheckHint.SENTRY_SYNTHETIC_EXCEPTION; + import ch.qos.logback.classic.Level; import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ThrowableProxy; @@ -17,6 +20,7 @@ import io.sentry.util.CollectionUtils; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -59,10 +63,16 @@ public void start() { @Override protected void append(@NotNull ILoggingEvent eventObject) { if (eventObject.getLevel().isGreaterOrEqual(minimumEventLevel)) { - Sentry.captureEvent(createEvent(eventObject)); + final Map hintMap = new HashMap<>(); + hintMap.put(SENTRY_SYNTHETIC_EXCEPTION, eventObject); + + Sentry.captureEvent(createEvent(eventObject), hintMap); } if (eventObject.getLevel().isGreaterOrEqual(minimumBreadcrumbLevel)) { - Sentry.addBreadcrumb(createBreadcrumb(eventObject)); + final Map hintMap = new HashMap<>(); + hintMap.put(LOGBACK_LOGGING_EVENT, eventObject); + + Sentry.addBreadcrumb(createBreadcrumb(eventObject), hintMap); } } diff --git a/sentry-openfeign/src/main/java/io/sentry/openfeign/SentryFeignClient.java b/sentry-openfeign/src/main/java/io/sentry/openfeign/SentryFeignClient.java index c8ea6a3f921..121ac287e00 100644 --- a/sentry-openfeign/src/main/java/io/sentry/openfeign/SentryFeignClient.java +++ b/sentry-openfeign/src/main/java/io/sentry/openfeign/SentryFeignClient.java @@ -1,5 +1,8 @@ package io.sentry.openfeign; +import static io.sentry.TypeCheckHint.OPEN_FEIGN_REQUEST; +import static io.sentry.TypeCheckHint.OPEN_FEIGN_RESPONSE; + import feign.Client; import feign.Request; import feign.Response; @@ -12,6 +15,7 @@ import java.io.IOException; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; import org.jetbrains.annotations.NotNull; @@ -87,7 +91,14 @@ private void addBreadcrumb(final @NotNull Request request, final @Nullable Respo if (response != null && response.body() != null && response.body().length() != null) { breadcrumb.setData("response_body_size", response.body().length()); } - hub.addBreadcrumb(breadcrumb); + + final Map hintMap = new HashMap<>(); + hintMap.put(OPEN_FEIGN_REQUEST, request); + if (response != null) { + hintMap.put(OPEN_FEIGN_RESPONSE, response); + } + + hub.addBreadcrumb(breadcrumb, hintMap); } static final class RequestWrapper { diff --git a/sentry-openfeign/src/test/kotlin/io/sentry/openfeign/SentryFeignClientTest.kt b/sentry-openfeign/src/test/kotlin/io/sentry/openfeign/SentryFeignClientTest.kt index c881625b2ee..ac459c35757 100644 --- a/sentry-openfeign/src/test/kotlin/io/sentry/openfeign/SentryFeignClientTest.kt +++ b/sentry-openfeign/src/test/kotlin/io/sentry/openfeign/SentryFeignClientTest.kt @@ -1,6 +1,7 @@ package io.sentry.openfeign import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.check import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.verify @@ -134,7 +135,8 @@ class SentryFeignClientTest { assertEquals("http", it.type) assertEquals(13, it.data["response_body_size"]) assertEquals(12, it.data["request_body_size"]) - } + }, + anyOrNull() ) } @@ -147,7 +149,8 @@ class SentryFeignClientTest { assertEquals("http", it.type) assertEquals(0, it.data["response_body_size"]) assertEquals(12, it.data["request_body_size"]) - } + }, + anyOrNull() ) } @@ -165,7 +168,8 @@ class SentryFeignClientTest { verify(fixture.hub).addBreadcrumb( check { assertEquals("http", it.type) - } + }, + anyOrNull() ) } diff --git a/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java b/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java index 409f58c81a9..0d963e0f9bc 100644 --- a/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java +++ b/sentry-samples/sentry-samples-console/src/main/java/io/sentry/samples/console/Main.java @@ -11,6 +11,8 @@ import io.sentry.protocol.Message; import io.sentry.protocol.User; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; public class Main { @@ -134,7 +136,10 @@ public static void main(String[] args) throws InterruptedException { message.setFormatted(String.format(messageContent, i, count)); SentryEvent event = new SentryEvent(); event.setMessage(message); - Sentry.captureEvent(event, SentryLevel.DEBUG); + + final Map hintsMap = new HashMap<>(); + hintsMap.put("level", SentryLevel.DEBUG); + Sentry.captureEvent(event, hintsMap); } // Performance feature @@ -166,7 +171,7 @@ public static void main(String[] args) throws InterruptedException { private static class SomeEventProcessor implements EventProcessor { @Override - public SentryEvent process(SentryEvent event, Object hint) { + public SentryEvent process(SentryEvent event, Map hint) { // Here you can modify the event as you need if (event.getLevel() != null && event.getLevel().ordinal() > SentryLevel.INFO.ordinal()) { event.addBreadcrumb(new Breadcrumb("Processed by " + SomeEventProcessor.class)); diff --git a/sentry-samples/sentry-samples-spring-boot/src/main/java/io/sentry/samples/spring/boot/CustomEventProcessor.java b/sentry-samples/sentry-samples-spring-boot/src/main/java/io/sentry/samples/spring/boot/CustomEventProcessor.java index 2b11d4406e4..c21763cc004 100644 --- a/sentry-samples/sentry-samples-spring-boot/src/main/java/io/sentry/samples/spring/boot/CustomEventProcessor.java +++ b/sentry-samples/sentry-samples-spring-boot/src/main/java/io/sentry/samples/spring/boot/CustomEventProcessor.java @@ -3,6 +3,7 @@ import io.sentry.EventProcessor; import io.sentry.SentryEvent; import io.sentry.protocol.SentryRuntime; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.springframework.boot.SpringBootVersion; @@ -25,7 +26,8 @@ public CustomEventProcessor() { } @Override - public @NotNull SentryEvent process(@NotNull SentryEvent event, @Nullable Object hint) { + public @NotNull SentryEvent process( + @NotNull SentryEvent event, @Nullable Map hint) { final SentryRuntime runtime = new SentryRuntime(); runtime.setVersion(springBootVersion); runtime.setName("Spring Boot"); diff --git a/sentry-servlet/src/main/java/io/sentry/servlet/SentryRequestHttpServletRequestProcessor.java b/sentry-servlet/src/main/java/io/sentry/servlet/SentryRequestHttpServletRequestProcessor.java index 4faf0bb9baf..5b6c53c464e 100644 --- a/sentry-servlet/src/main/java/io/sentry/servlet/SentryRequestHttpServletRequestProcessor.java +++ b/sentry-servlet/src/main/java/io/sentry/servlet/SentryRequestHttpServletRequestProcessor.java @@ -29,7 +29,8 @@ public SentryRequestHttpServletRequestProcessor(@NotNull HttpServletRequest http // httpRequest.getRequestURL() returns StringBuffer which is considered an obsolete class. @SuppressWarnings("JdkObsolete") @Override - public @NotNull SentryEvent process(@NotNull SentryEvent event, @Nullable Object hint) { + public @NotNull SentryEvent process( + @NotNull SentryEvent event, @Nullable Map hint) { final Request sentryRequest = new Request(); sentryRequest.setMethod(httpRequest.getMethod()); sentryRequest.setQueryString(httpRequest.getQueryString()); diff --git a/sentry-servlet/src/main/java/io/sentry/servlet/SentryServletRequestListener.java b/sentry-servlet/src/main/java/io/sentry/servlet/SentryServletRequestListener.java index 90dfd5ddc35..2050b78e14d 100644 --- a/sentry-servlet/src/main/java/io/sentry/servlet/SentryServletRequestListener.java +++ b/sentry-servlet/src/main/java/io/sentry/servlet/SentryServletRequestListener.java @@ -1,10 +1,14 @@ package io.sentry.servlet; +import static io.sentry.TypeCheckHint.SERVLET_REQUEST; + import com.jakewharton.nopen.annotation.Open; import io.sentry.Breadcrumb; import io.sentry.HubAdapter; import io.sentry.IHub; import io.sentry.util.Objects; +import java.util.HashMap; +import java.util.Map; import javax.servlet.ServletRequest; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; @@ -41,7 +45,11 @@ public void requestInitialized(@NotNull ServletRequestEvent servletRequestEvent) if (servletRequest instanceof HttpServletRequest) { final HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; - hub.addBreadcrumb(Breadcrumb.http(httpRequest.getRequestURI(), httpRequest.getMethod())); + final Map hintMap = new HashMap<>(); + hintMap.put(SERVLET_REQUEST, httpRequest); + + hub.addBreadcrumb( + Breadcrumb.http(httpRequest.getRequestURI(), httpRequest.getMethod()), hintMap); hub.configureScope( scope -> { diff --git a/sentry-servlet/src/test/kotlin/io/sentry/servlet/SentryServletRequestListenerTest.kt b/sentry-servlet/src/test/kotlin/io/sentry/servlet/SentryServletRequestListenerTest.kt index e29a2cfc192..386c097760e 100644 --- a/sentry-servlet/src/test/kotlin/io/sentry/servlet/SentryServletRequestListenerTest.kt +++ b/sentry-servlet/src/test/kotlin/io/sentry/servlet/SentryServletRequestListenerTest.kt @@ -1,5 +1,6 @@ package io.sentry.servlet +import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.check import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.verify @@ -43,7 +44,8 @@ class SentryServletRequestListenerTest { assertThat(it.getData("url")).isEqualTo("http://localhost:8080/some-uri") assertThat(it.getData("method")).isEqualTo("POST") assertThat(it.type).isEqualTo("http") - } + }, + anyOrNull() ) } diff --git a/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt b/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt index 8365e222182..00a7135a7fc 100644 --- a/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt +++ b/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt @@ -661,7 +661,7 @@ class SentryAutoConfigurationTest { } class CustomBeforeSendCallback : SentryOptions.BeforeSendCallback { - override fun execute(event: SentryEvent, hint: Any?): SentryEvent? = null + override fun execute(event: SentryEvent, hint: Map?): SentryEvent? = null } @Configuration(proxyBeanMethods = false) @@ -672,7 +672,7 @@ class SentryAutoConfigurationTest { } class CustomBeforeBreadcrumbCallback : SentryOptions.BeforeBreadcrumbCallback { - override fun execute(breadcrumb: Breadcrumb, hint: Any?): Breadcrumb? = null + override fun execute(breadcrumb: Breadcrumb, hint: Map?): Breadcrumb? = null } @Configuration(proxyBeanMethods = false) @@ -683,7 +683,7 @@ class SentryAutoConfigurationTest { } class CustomEventProcessor : EventProcessor { - override fun process(event: SentryEvent, hint: Any?) = null + override fun process(event: SentryEvent, hint: Map?) = null } @Configuration(proxyBeanMethods = false) diff --git a/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanRestTemplateCustomizerTest.kt b/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanRestTemplateCustomizerTest.kt index c635da217b9..3f87cf9f236 100644 --- a/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanRestTemplateCustomizerTest.kt +++ b/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanRestTemplateCustomizerTest.kt @@ -1,5 +1,6 @@ package io.sentry.spring.boot +import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.check import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.verify @@ -147,7 +148,8 @@ class SentrySpanRestTemplateCustomizerTest { assertEquals(fixture.url, it.data["url"]) assertEquals("POST", it.data["method"]) assertEquals(7, it.data["request_body_size"]) - } + }, + anyOrNull() ) } @@ -163,7 +165,8 @@ class SentrySpanRestTemplateCustomizerTest { assertEquals("http", it.type) assertEquals(fixture.url, it.data["url"]) assertEquals("GET", it.data["method"]) - } + }, + anyOrNull() ) } @@ -176,7 +179,8 @@ class SentrySpanRestTemplateCustomizerTest { assertEquals(fixture.url, it.data["url"]) assertEquals("POST", it.data["method"]) assertEquals(7, it.data["request_body_size"]) - } + }, + anyOrNull() ) } @@ -192,7 +196,8 @@ class SentrySpanRestTemplateCustomizerTest { assertEquals("http", it.type) assertEquals(fixture.url, it.data["url"]) assertEquals("GET", it.data["method"]) - } + }, + anyOrNull() ) } } diff --git a/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanWebClientCustomizerTest.kt b/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanWebClientCustomizerTest.kt index a49ac934b9f..8cb5bee0e8c 100644 --- a/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanWebClientCustomizerTest.kt +++ b/sentry-spring-boot-starter/src/test/kotlin/io/sentry/spring/boot/SentrySpanWebClientCustomizerTest.kt @@ -1,5 +1,6 @@ package io.sentry.spring.boot +import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.check import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.verify @@ -201,7 +202,8 @@ class SentrySpanWebClientCustomizerTest { assertEquals("http", it.type) assertEquals(uri.toString(), it.data["url"]) assertEquals("POST", it.data["method"]) - } + }, + anyOrNull() ) } @@ -223,7 +225,8 @@ class SentrySpanWebClientCustomizerTest { assertEquals("http", it.type) assertEquals(uri.toString(), it.data["url"]) assertEquals("GET", it.data["method"]) - } + }, + anyOrNull() ) } @@ -242,7 +245,8 @@ class SentrySpanWebClientCustomizerTest { assertEquals("http", it.type) assertEquals(uri.toString(), it.data["url"]) assertEquals("POST", it.data["method"]) - } + }, + anyOrNull() ) } @@ -264,7 +268,8 @@ class SentrySpanWebClientCustomizerTest { assertEquals("http", it.type) assertEquals(uri.toString(), it.data["url"]) assertEquals("GET", it.data["method"]) - } + }, + anyOrNull() ) } } diff --git a/sentry-spring/api/sentry-spring.api b/sentry-spring/api/sentry-spring.api index 74603b6af2b..dfe84709bca 100644 --- a/sentry-spring/api/sentry-spring.api +++ b/sentry-spring/api/sentry-spring.api @@ -36,7 +36,7 @@ public class io/sentry/spring/SentryInitBeanPostProcessor : org/springframework/ public class io/sentry/spring/SentryRequestHttpServletRequestProcessor : io/sentry/EventProcessor { public fun (Lio/sentry/spring/tracing/TransactionNameProvider;Ljavax/servlet/http/HttpServletRequest;)V - public fun process (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/SentryEvent; + public fun process (Lio/sentry/SentryEvent;Ljava/util/Map;)Lio/sentry/SentryEvent; } public class io/sentry/spring/SentryRequestResolver { diff --git a/sentry-spring/src/main/java/io/sentry/spring/SentryExceptionResolver.java b/sentry-spring/src/main/java/io/sentry/spring/SentryExceptionResolver.java index 115a10a4ee9..1c8cc9d2414 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/SentryExceptionResolver.java +++ b/sentry-spring/src/main/java/io/sentry/spring/SentryExceptionResolver.java @@ -1,5 +1,8 @@ package io.sentry.spring; +import static io.sentry.TypeCheckHint.SPRING_RESOLVER_REQUEST; +import static io.sentry.TypeCheckHint.SPRING_RESOLVER_RESPONSE; + import com.jakewharton.nopen.annotation.Open; import io.sentry.IHub; import io.sentry.SentryEvent; @@ -8,6 +11,8 @@ import io.sentry.protocol.Mechanism; import io.sentry.spring.tracing.TransactionNameProvider; import io.sentry.util.Objects; +import java.util.HashMap; +import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jetbrains.annotations.NotNull; @@ -54,7 +59,12 @@ public SentryExceptionResolver( final SentryEvent event = new SentryEvent(throwable); event.setLevel(SentryLevel.FATAL); event.setTransaction(transactionNameProvider.provideTransactionName(request)); - hub.captureEvent(event); + + final Map hintMap = new HashMap<>(); + hintMap.put(SPRING_RESOLVER_REQUEST, request); + hintMap.put(SPRING_RESOLVER_RESPONSE, response); + + hub.captureEvent(event, hintMap); // null = run other HandlerExceptionResolvers to actually handle the exception return null; diff --git a/sentry-spring/src/main/java/io/sentry/spring/SentryRequestHttpServletRequestProcessor.java b/sentry-spring/src/main/java/io/sentry/spring/SentryRequestHttpServletRequestProcessor.java index 3f989591b95..4d62dbd3acc 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/SentryRequestHttpServletRequestProcessor.java +++ b/sentry-spring/src/main/java/io/sentry/spring/SentryRequestHttpServletRequestProcessor.java @@ -5,6 +5,7 @@ import io.sentry.SentryEvent; import io.sentry.spring.tracing.TransactionNameProvider; import io.sentry.util.Objects; +import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -25,7 +26,7 @@ public SentryRequestHttpServletRequestProcessor( @Override public @NotNull SentryEvent process( - final @NotNull SentryEvent event, final @Nullable Object hint) { + final @NotNull SentryEvent event, final @Nullable Map hint) { if (event.getTransaction() == null) { event.setTransaction(transactionNameProvider.provideTransactionName(request)); } diff --git a/sentry-spring/src/main/java/io/sentry/spring/SentrySpringFilter.java b/sentry-spring/src/main/java/io/sentry/spring/SentrySpringFilter.java index dbcaa2a99d4..a33d2103d09 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/SentrySpringFilter.java +++ b/sentry-spring/src/main/java/io/sentry/spring/SentrySpringFilter.java @@ -1,6 +1,8 @@ package io.sentry.spring; import static io.sentry.SentryOptions.RequestSize.*; +import static io.sentry.TypeCheckHint.SPRING_REQUEST_FILTER_REQUEST; +import static io.sentry.TypeCheckHint.SPRING_REQUEST_FILTER_RESPONSE; import com.jakewharton.nopen.annotation.Open; import io.sentry.Breadcrumb; @@ -15,6 +17,8 @@ import io.sentry.spring.tracing.TransactionNameProvider; import io.sentry.util.Objects; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -60,7 +64,11 @@ protected void doFilterInternal( final HttpServletRequest request = resolveHttpServletRequest(servletRequest); hub.pushScope(); try { - hub.addBreadcrumb(Breadcrumb.http(request.getRequestURI(), request.getMethod())); + final Map hintMap = new HashMap<>(); + hintMap.put(SPRING_REQUEST_FILTER_REQUEST, servletRequest); + hintMap.put(SPRING_REQUEST_FILTER_RESPONSE, response); + + hub.addBreadcrumb(Breadcrumb.http(request.getRequestURI(), request.getMethod()), hintMap); configureScope(request); filterChain.doFilter(request, response); } finally { @@ -142,7 +150,8 @@ public RequestBodyExtractingEventProcessor( } @Override - public @NotNull SentryEvent process(@NotNull SentryEvent event, @Nullable Object hint) { + public @NotNull SentryEvent process( + @NotNull SentryEvent event, @Nullable Map hint) { if (event.getRequest() != null) { event.getRequest().setData(requestPayloadExtractor.extract(request, options)); } diff --git a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientHttpRequestInterceptor.java b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientHttpRequestInterceptor.java index 30b66fafea5..ad8fc1682a9 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientHttpRequestInterceptor.java +++ b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientHttpRequestInterceptor.java @@ -1,5 +1,9 @@ package io.sentry.spring.tracing; +import static io.sentry.TypeCheckHint.SPRING_REQUEST_INTERCEPTOR_REQUEST; +import static io.sentry.TypeCheckHint.SPRING_REQUEST_INTERCEPTOR_REQUEST_BODY; +import static io.sentry.TypeCheckHint.SPRING_REQUEST_INTERCEPTOR_RESPONSE; + import com.jakewharton.nopen.annotation.Open; import io.sentry.Breadcrumb; import io.sentry.IHub; @@ -9,6 +13,8 @@ import io.sentry.TracingOrigins; import io.sentry.util.Objects; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.springframework.http.HttpRequest; @@ -31,6 +37,7 @@ public SentrySpanClientHttpRequestInterceptor(final @NotNull IHub hub) { @NotNull ClientHttpRequestExecution execution) throws IOException { Integer responseStatusCode = null; + ClientHttpResponse response = null; try { final ISpan activeSpan = hub.getSpan(); if (activeSpan == null) { @@ -47,7 +54,7 @@ public SentrySpanClientHttpRequestInterceptor(final @NotNull IHub hub) { } try { - final ClientHttpResponse response = execution.execute(request, body); + response = execution.execute(request, body); // handles both success and error responses span.setStatus(SpanStatus.fromHttpStatusCode(response.getRawStatusCode())); responseStatusCode = response.getRawStatusCode(); @@ -61,17 +68,26 @@ public SentrySpanClientHttpRequestInterceptor(final @NotNull IHub hub) { span.finish(); } } finally { - addBreadcrumb(request, body, responseStatusCode); + addBreadcrumb(request, body, responseStatusCode, response); } } private void addBreadcrumb( final @NotNull HttpRequest request, final @NotNull byte[] body, - final @Nullable Integer responseStatusCode) { + final @Nullable Integer responseStatusCode, + final @Nullable ClientHttpResponse response) { final Breadcrumb breadcrumb = Breadcrumb.http(request.getURI().toString(), request.getMethodValue(), responseStatusCode); breadcrumb.setData("request_body_size", body.length); - hub.addBreadcrumb(breadcrumb); + + final Map hintMap = new HashMap<>(); + hintMap.put(SPRING_REQUEST_INTERCEPTOR_REQUEST, request); + hintMap.put(SPRING_REQUEST_INTERCEPTOR_REQUEST_BODY, body); + if (response != null) { + hintMap.put(SPRING_REQUEST_INTERCEPTOR_RESPONSE, response); + } + + hub.addBreadcrumb(breadcrumb, hintMap); } } diff --git a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientWebRequestFilter.java b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientWebRequestFilter.java index 8ae5de17a1d..17a8650a276 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientWebRequestFilter.java +++ b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentrySpanClientWebRequestFilter.java @@ -1,5 +1,8 @@ package io.sentry.spring.tracing; +import static io.sentry.TypeCheckHint.SPRING_EXCHANGE_FILTER_REQUEST; +import static io.sentry.TypeCheckHint.SPRING_EXCHANGE_FILTER_RESPONSE; + import com.jakewharton.nopen.annotation.Open; import io.sentry.Breadcrumb; import io.sentry.IHub; @@ -8,6 +11,8 @@ import io.sentry.SpanStatus; import io.sentry.TracingOrigins; import io.sentry.util.Objects; +import java.util.HashMap; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.springframework.web.reactive.function.client.ClientRequest; @@ -50,7 +55,7 @@ public SentrySpanClientWebRequestFilter(final @NotNull IHub hub) { .flatMap( response -> { span.setStatus(SpanStatus.fromHttpStatusCode(response.rawStatusCode())); - addBreadcrumb(request, response.rawStatusCode()); + addBreadcrumb(request, response); span.finish(); return Mono.just(response); }) @@ -65,9 +70,19 @@ public SentrySpanClientWebRequestFilter(final @NotNull IHub hub) { } private void addBreadcrumb( - final @NotNull ClientRequest request, final @Nullable Integer responseStatusCode) { + final @NotNull ClientRequest request, final @Nullable ClientResponse response) { final Breadcrumb breadcrumb = - Breadcrumb.http(request.url().toString(), request.method().name(), responseStatusCode); - hub.addBreadcrumb(breadcrumb); + Breadcrumb.http( + request.url().toString(), + request.method().name(), + response != null ? response.rawStatusCode() : null); + + final Map hintMap = new HashMap<>(); + hintMap.put(SPRING_EXCHANGE_FILTER_REQUEST, request); + if (response != null) { + hintMap.put(SPRING_EXCHANGE_FILTER_RESPONSE, response); + } + + hub.addBreadcrumb(breadcrumb, hintMap); } } diff --git a/sentry-spring/src/main/java/io/sentry/spring/webflux/SentryWebExceptionHandler.java b/sentry-spring/src/main/java/io/sentry/spring/webflux/SentryWebExceptionHandler.java index 97473cdca83..38d7750d814 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/webflux/SentryWebExceptionHandler.java +++ b/sentry-spring/src/main/java/io/sentry/spring/webflux/SentryWebExceptionHandler.java @@ -1,11 +1,16 @@ package io.sentry.spring.webflux; +import static io.sentry.TypeCheckHint.WEBFLUX_EXCEPTION_HANDLER_REQUEST; +import static io.sentry.TypeCheckHint.WEBFLUX_EXCEPTION_HANDLER_RESPONSE; + import io.sentry.IHub; import io.sentry.SentryEvent; import io.sentry.SentryLevel; import io.sentry.exception.ExceptionMechanismException; import io.sentry.protocol.Mechanism; import io.sentry.util.Objects; +import java.util.HashMap; +import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.springframework.core.annotation.Order; @@ -38,7 +43,12 @@ public SentryWebExceptionHandler(final @NotNull IHub hub) { final SentryEvent event = new SentryEvent(throwable); event.setLevel(SentryLevel.FATAL); event.setTransaction(TransactionNameProvider.provideTransactionName(serverWebExchange)); - hub.captureEvent(event); + + final Map hintMap = new HashMap<>(); + hintMap.put(WEBFLUX_EXCEPTION_HANDLER_REQUEST, serverWebExchange.getRequest()); + hintMap.put(WEBFLUX_EXCEPTION_HANDLER_RESPONSE, serverWebExchange.getResponse()); + + hub.captureEvent(event, hintMap); } return Mono.error(ex); } diff --git a/sentry-spring/src/main/java/io/sentry/spring/webflux/SentryWebFilter.java b/sentry-spring/src/main/java/io/sentry/spring/webflux/SentryWebFilter.java index 4bc544dfc72..8cd060779af 100644 --- a/sentry-spring/src/main/java/io/sentry/spring/webflux/SentryWebFilter.java +++ b/sentry-spring/src/main/java/io/sentry/spring/webflux/SentryWebFilter.java @@ -1,11 +1,17 @@ package io.sentry.spring.webflux; +import static io.sentry.TypeCheckHint.WEBFLUX_FILTER_REQUEST; +import static io.sentry.TypeCheckHint.WEBFLUX_FILTER_RESPONSE; + import io.sentry.Breadcrumb; import io.sentry.IHub; import io.sentry.util.Objects; +import java.util.HashMap; +import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.springframework.http.server.reactive.ServerHttpRequest; +import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; @@ -36,8 +42,14 @@ public Mono filter( () -> { hub.pushScope(); final ServerHttpRequest request = serverWebExchange.getRequest(); + final ServerHttpResponse response = serverWebExchange.getResponse(); + + final Map hintMap = new HashMap<>(); + hintMap.put(WEBFLUX_FILTER_REQUEST, request); + hintMap.put(WEBFLUX_FILTER_RESPONSE, response); + hub.addBreadcrumb( - Breadcrumb.http(request.getURI().toString(), request.getMethodValue())); + Breadcrumb.http(request.getURI().toString(), request.getMethodValue()), hintMap); hub.configureScope( scope -> scope.setRequest(sentryRequestResolver.resolveSentryRequest(request))); }); diff --git a/sentry-spring/src/test/kotlin/io/sentry/spring/SentrySpringFilterTest.kt b/sentry-spring/src/test/kotlin/io/sentry/spring/SentrySpringFilterTest.kt index 2f8cf81b289..47849224a46 100644 --- a/sentry-spring/src/test/kotlin/io/sentry/spring/SentrySpringFilterTest.kt +++ b/sentry-spring/src/test/kotlin/io/sentry/spring/SentrySpringFilterTest.kt @@ -1,6 +1,7 @@ package io.sentry.spring import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.anyOrNull import com.nhaarman.mockitokotlin2.check import com.nhaarman.mockitokotlin2.doAnswer import com.nhaarman.mockitokotlin2.mock @@ -74,7 +75,8 @@ class SentrySpringFilterTest { Assertions.assertThat(it.getData("url")).isEqualTo("http://localhost:8080/some-uri") Assertions.assertThat(it.getData("method")).isEqualTo("POST") Assertions.assertThat(it.type).isEqualTo("http") - } + }, + anyOrNull() ) } diff --git a/sentry-spring/src/test/kotlin/io/sentry/spring/tracing/SentryTracingFilterTest.kt b/sentry-spring/src/test/kotlin/io/sentry/spring/tracing/SentryTracingFilterTest.kt index a8ddd6af215..0ac76e964d6 100644 --- a/sentry-spring/src/test/kotlin/io/sentry/spring/tracing/SentryTracingFilterTest.kt +++ b/sentry-spring/src/test/kotlin/io/sentry/spring/tracing/SentryTracingFilterTest.kt @@ -15,6 +15,7 @@ import io.sentry.SentryOptions import io.sentry.SentryTracer import io.sentry.SpanId import io.sentry.SpanStatus +import io.sentry.TraceState import io.sentry.TransactionContext import io.sentry.protocol.SentryId import org.assertj.core.api.Assertions.assertThat @@ -83,7 +84,7 @@ class SentryTracingFilterTest { assertThat(it.contexts.trace!!.status).isEqualTo(SpanStatus.OK) assertThat(it.contexts.trace!!.operation).isEqualTo("http.server") }, - anyOrNull() + anyOrNull() ) } @@ -97,7 +98,7 @@ class SentryTracingFilterTest { check { assertThat(it.contexts.trace!!.status).isEqualTo(SpanStatus.INTERNAL_ERROR) }, - anyOrNull() + anyOrNull() ) } @@ -111,7 +112,7 @@ class SentryTracingFilterTest { check { assertThat(it.contexts.trace!!.status).isNull() }, - anyOrNull() + anyOrNull() ) } @@ -125,7 +126,7 @@ class SentryTracingFilterTest { check { assertThat(it.contexts.trace!!.parentSpanId).isNull() }, - anyOrNull() + anyOrNull() ) } @@ -140,7 +141,7 @@ class SentryTracingFilterTest { check { assertThat(it.contexts.trace!!.parentSpanId).isEqualTo(parentSpanId) }, - anyOrNull() + anyOrNull() ) } @@ -171,7 +172,7 @@ class SentryTracingFilterTest { check { assertThat(it.status).isEqualTo(SpanStatus.INTERNAL_ERROR) }, - anyOrNull() + anyOrNull() ) } } diff --git a/sentry-spring/src/test/kotlin/io/sentry/spring/tracing/SentryTransactionAdviceTest.kt b/sentry-spring/src/test/kotlin/io/sentry/spring/tracing/SentryTransactionAdviceTest.kt index b8f1364a703..8ded5a39b26 100644 --- a/sentry-spring/src/test/kotlin/io/sentry/spring/tracing/SentryTransactionAdviceTest.kt +++ b/sentry-spring/src/test/kotlin/io/sentry/spring/tracing/SentryTransactionAdviceTest.kt @@ -13,6 +13,7 @@ import io.sentry.IHub import io.sentry.SentryOptions import io.sentry.SentryTracer import io.sentry.SpanStatus +import io.sentry.TraceState import io.sentry.TransactionContext import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.assertThrows @@ -63,7 +64,7 @@ class SentryTransactionAdviceTest { assertThat(it.contexts.trace!!.operation).isEqualTo("bean") assertThat(it.status).isEqualTo(SpanStatus.OK) }, - anyOrNull() + anyOrNull() ) } @@ -74,7 +75,7 @@ class SentryTransactionAdviceTest { check { assertThat(it.status).isEqualTo(SpanStatus.INTERNAL_ERROR) }, - anyOrNull() + anyOrNull() ) } @@ -86,7 +87,7 @@ class SentryTransactionAdviceTest { assertThat(it.transaction).isEqualTo("SampleService.methodWithoutTransactionNameSet") assertThat(it.contexts.trace!!.operation).isEqualTo("op") }, - anyOrNull() + anyOrNull() ) } @@ -96,7 +97,7 @@ class SentryTransactionAdviceTest { sampleService.methodWithTransactionNameSet() - verify(hub, times(0)).captureTransaction(any(), any()) + verify(hub, times(0)).captureTransaction(any(), any()) } @Test @@ -107,7 +108,7 @@ class SentryTransactionAdviceTest { assertThat(it.transaction).isEqualTo("ClassAnnotatedSampleService.hello") assertThat(it.contexts.trace!!.operation).isEqualTo("op") }, - anyOrNull() + anyOrNull() ) } @@ -119,7 +120,7 @@ class SentryTransactionAdviceTest { assertThat(it.transaction).isEqualTo("ClassAnnotatedWithOperationSampleService.hello") assertThat(it.contexts.trace!!.operation).isEqualTo("my-op") }, - anyOrNull() + anyOrNull() ) } diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 9cc83a29513..4f971c653d8 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -103,7 +103,7 @@ public final class io/sentry/DiagnosticLogger : io/sentry/ILogger { public final class io/sentry/DuplicateEventDetectionEventProcessor : io/sentry/EventProcessor { public fun (Lio/sentry/SentryOptions;)V - public fun process (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/SentryEvent; + public fun process (Lio/sentry/SentryEvent;Ljava/util/Map;)Lio/sentry/SentryEvent; } public final class io/sentry/EnvelopeReader : io/sentry/IEnvelopeReader { @@ -114,12 +114,12 @@ public final class io/sentry/EnvelopeReader : io/sentry/IEnvelopeReader { public final class io/sentry/EnvelopeSender : io/sentry/IEnvelopeSender { public fun (Lio/sentry/IHub;Lio/sentry/ISerializer;Lio/sentry/ILogger;J)V public synthetic fun processDirectory (Ljava/io/File;)V - public fun processEnvelopeFile (Ljava/lang/String;Ljava/lang/Object;)V + public fun processEnvelopeFile (Ljava/lang/String;Ljava/util/Map;)V } public abstract interface class io/sentry/EventProcessor { - public fun process (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/SentryEvent; - public fun process (Lio/sentry/protocol/SentryTransaction;Ljava/lang/Object;)Lio/sentry/protocol/SentryTransaction; + public fun process (Lio/sentry/SentryEvent;Ljava/util/Map;)Lio/sentry/SentryEvent; + public fun process (Lio/sentry/protocol/SentryTransaction;Ljava/util/Map;)Lio/sentry/protocol/SentryTransaction; } public final class io/sentry/ExternalOptions { @@ -165,13 +165,13 @@ public final class io/sentry/ExternalOptions { public final class io/sentry/Hub : io/sentry/IHub { public fun (Lio/sentry/SentryOptions;)V - public fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/lang/Object;)V + public fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/util/Map;)V public fun bindClient (Lio/sentry/ISentryClient;)V - public fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; - public fun captureEvent (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; - public fun captureException (Ljava/lang/Throwable;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; + public fun captureEvent (Lio/sentry/SentryEvent;Ljava/util/Map;)Lio/sentry/protocol/SentryId; + public fun captureException (Ljava/lang/Throwable;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureMessage (Ljava/lang/String;Lio/sentry/SentryLevel;)Lio/sentry/protocol/SentryId; - public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureUserFeedback (Lio/sentry/UserFeedback;)V public fun clearBreadcrumbs ()V public fun clone ()Lio/sentry/IHub; @@ -205,13 +205,13 @@ public final class io/sentry/Hub : io/sentry/IHub { } public final class io/sentry/HubAdapter : io/sentry/IHub { - public fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/lang/Object;)V + public fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/util/Map;)V public fun bindClient (Lio/sentry/ISentryClient;)V - public fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; - public fun captureEvent (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; - public fun captureException (Ljava/lang/Throwable;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; + public fun captureEvent (Lio/sentry/SentryEvent;Ljava/util/Map;)Lio/sentry/protocol/SentryId; + public fun captureException (Ljava/lang/Throwable;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureMessage (Ljava/lang/String;Lio/sentry/SentryLevel;)Lio/sentry/protocol/SentryId; - public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureUserFeedback (Lio/sentry/UserFeedback;)V public fun clearBreadcrumbs ()V public fun clone ()Lio/sentry/IHub; @@ -251,26 +251,26 @@ public abstract interface class io/sentry/IEnvelopeReader { } public abstract interface class io/sentry/IEnvelopeSender { - public abstract fun processEnvelopeFile (Ljava/lang/String;Ljava/lang/Object;)V + public abstract fun processEnvelopeFile (Ljava/lang/String;Ljava/util/Map;)V } public abstract interface class io/sentry/IHub { public fun addBreadcrumb (Lio/sentry/Breadcrumb;)V - public abstract fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/lang/Object;)V + public abstract fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/util/Map;)V public fun addBreadcrumb (Ljava/lang/String;)V public fun addBreadcrumb (Ljava/lang/String;Ljava/lang/String;)V public abstract fun bindClient (Lio/sentry/ISentryClient;)V public fun captureEnvelope (Lio/sentry/SentryEnvelope;)Lio/sentry/protocol/SentryId; - public abstract fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public abstract fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureEvent (Lio/sentry/SentryEvent;)Lio/sentry/protocol/SentryId; - public abstract fun captureEvent (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public abstract fun captureEvent (Lio/sentry/SentryEvent;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureException (Ljava/lang/Throwable;)Lio/sentry/protocol/SentryId; - public abstract fun captureException (Ljava/lang/Throwable;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public abstract fun captureException (Ljava/lang/Throwable;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureMessage (Ljava/lang/String;)Lio/sentry/protocol/SentryId; public abstract fun captureMessage (Ljava/lang/String;Lio/sentry/SentryLevel;)Lio/sentry/protocol/SentryId; public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;)Lio/sentry/protocol/SentryId; - public abstract fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; - public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public abstract fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Ljava/util/Map;)Lio/sentry/protocol/SentryId; + public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public abstract fun captureUserFeedback (Lio/sentry/UserFeedback;)V public abstract fun clearBreadcrumbs ()V public abstract fun clone ()Lio/sentry/IHub; @@ -328,23 +328,23 @@ public abstract interface class io/sentry/IScopeObserver { public abstract interface class io/sentry/ISentryClient { public fun captureEnvelope (Lio/sentry/SentryEnvelope;)Lio/sentry/protocol/SentryId; - public abstract fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public abstract fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureEvent (Lio/sentry/SentryEvent;)Lio/sentry/protocol/SentryId; public fun captureEvent (Lio/sentry/SentryEvent;Lio/sentry/Scope;)Lio/sentry/protocol/SentryId; - public abstract fun captureEvent (Lio/sentry/SentryEvent;Lio/sentry/Scope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; - public fun captureEvent (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public abstract fun captureEvent (Lio/sentry/SentryEvent;Lio/sentry/Scope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; + public fun captureEvent (Lio/sentry/SentryEvent;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureException (Ljava/lang/Throwable;)Lio/sentry/protocol/SentryId; public fun captureException (Ljava/lang/Throwable;Lio/sentry/Scope;)Lio/sentry/protocol/SentryId; - public fun captureException (Ljava/lang/Throwable;Lio/sentry/Scope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; - public fun captureException (Ljava/lang/Throwable;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public fun captureException (Ljava/lang/Throwable;Lio/sentry/Scope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; + public fun captureException (Ljava/lang/Throwable;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureMessage (Ljava/lang/String;Lio/sentry/SentryLevel;)Lio/sentry/protocol/SentryId; public fun captureMessage (Ljava/lang/String;Lio/sentry/SentryLevel;Lio/sentry/Scope;)Lio/sentry/protocol/SentryId; public fun captureSession (Lio/sentry/Session;)V - public abstract fun captureSession (Lio/sentry/Session;Ljava/lang/Object;)V + public abstract fun captureSession (Lio/sentry/Session;Ljava/util/Map;)V public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;)Lio/sentry/protocol/SentryId; - public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/Scope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/Scope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;)Lio/sentry/protocol/SentryId; - public abstract fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Lio/sentry/Scope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public abstract fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Lio/sentry/Scope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public abstract fun captureUserFeedback (Lio/sentry/UserFeedback;)V public abstract fun close ()V public abstract fun flush (J)V @@ -470,8 +470,8 @@ public abstract interface class io/sentry/JsonUnknown { public final class io/sentry/MainEventProcessor : io/sentry/EventProcessor, java/io/Closeable { public fun close ()V - public fun process (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/SentryEvent; - public fun process (Lio/sentry/protocol/SentryTransaction;Ljava/lang/Object;)Lio/sentry/protocol/SentryTransaction; + public fun process (Lio/sentry/SentryEvent;Ljava/util/Map;)Lio/sentry/SentryEvent; + public fun process (Lio/sentry/protocol/SentryTransaction;Ljava/util/Map;)Lio/sentry/protocol/SentryTransaction; } public final class io/sentry/NoOpEnvelopeReader : io/sentry/IEnvelopeReader { @@ -480,13 +480,13 @@ public final class io/sentry/NoOpEnvelopeReader : io/sentry/IEnvelopeReader { } public final class io/sentry/NoOpHub : io/sentry/IHub { - public fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/lang/Object;)V + public fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/util/Map;)V public fun bindClient (Lio/sentry/ISentryClient;)V - public fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; - public fun captureEvent (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; - public fun captureException (Ljava/lang/Throwable;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; + public fun captureEvent (Lio/sentry/SentryEvent;Ljava/util/Map;)Lio/sentry/protocol/SentryId; + public fun captureException (Ljava/lang/Throwable;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureMessage (Ljava/lang/String;Lio/sentry/SentryLevel;)Lio/sentry/protocol/SentryId; - public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureUserFeedback (Lio/sentry/UserFeedback;)V public fun clearBreadcrumbs ()V public fun clone ()Lio/sentry/IHub; @@ -600,7 +600,7 @@ public final class io/sentry/OptionsContainer { public final class io/sentry/OutboxSender : io/sentry/IEnvelopeSender { public fun (Lio/sentry/IHub;Lio/sentry/IEnvelopeReader;Lio/sentry/ISerializer;Lio/sentry/ILogger;J)V public synthetic fun processDirectory (Ljava/io/File;)V - public fun processEnvelopeFile (Ljava/lang/String;Ljava/lang/Object;)V + public fun processEnvelopeFile (Ljava/lang/String;Ljava/util/Map;)V } public final class io/sentry/RequestDetails { @@ -619,7 +619,7 @@ public final class io/sentry/Scope { public fun (Lio/sentry/SentryOptions;)V public fun addAttachment (Lio/sentry/Attachment;)V public fun addBreadcrumb (Lio/sentry/Breadcrumb;)V - public fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/lang/Object;)V + public fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/util/Map;)V public fun addEventProcessor (Lio/sentry/EventProcessor;)V public fun clear ()V public fun clearAttachments ()V @@ -693,14 +693,14 @@ public final class io/sentry/SendFireAndForgetOutboxSender : io/sentry/SendCache public final class io/sentry/Sentry { public static fun addBreadcrumb (Lio/sentry/Breadcrumb;)V - public static fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/lang/Object;)V + public static fun addBreadcrumb (Lio/sentry/Breadcrumb;Ljava/util/Map;)V public static fun addBreadcrumb (Ljava/lang/String;)V public static fun addBreadcrumb (Ljava/lang/String;Ljava/lang/String;)V public static fun bindClient (Lio/sentry/ISentryClient;)V public static fun captureEvent (Lio/sentry/SentryEvent;)Lio/sentry/protocol/SentryId; - public static fun captureEvent (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public static fun captureEvent (Lio/sentry/SentryEvent;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public static fun captureException (Ljava/lang/Throwable;)Lio/sentry/protocol/SentryId; - public static fun captureException (Ljava/lang/Throwable;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public static fun captureException (Ljava/lang/Throwable;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public static fun captureMessage (Ljava/lang/String;)Lio/sentry/protocol/SentryId; public static fun captureMessage (Ljava/lang/String;Lio/sentry/SentryLevel;)Lio/sentry/protocol/SentryId; public static fun captureUserFeedback (Lio/sentry/UserFeedback;)V @@ -822,10 +822,10 @@ public final class io/sentry/SentryBaseEvent$Serializer { } public final class io/sentry/SentryClient : io/sentry/ISentryClient { - public fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; - public fun captureEvent (Lio/sentry/SentryEvent;Lio/sentry/Scope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; - public fun captureSession (Lio/sentry/Session;Ljava/lang/Object;)V - public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Lio/sentry/Scope;Ljava/lang/Object;)Lio/sentry/protocol/SentryId; + public fun captureEnvelope (Lio/sentry/SentryEnvelope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; + public fun captureEvent (Lio/sentry/SentryEvent;Lio/sentry/Scope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; + public fun captureSession (Lio/sentry/Session;Ljava/util/Map;)V + public fun captureTransaction (Lio/sentry/protocol/SentryTransaction;Lio/sentry/TraceState;Lio/sentry/Scope;Ljava/util/Map;)Lio/sentry/protocol/SentryId; public fun captureUserFeedback (Lio/sentry/UserFeedback;)V public fun close ()V public fun flush (J)V @@ -1118,11 +1118,11 @@ public class io/sentry/SentryOptions { } public abstract interface class io/sentry/SentryOptions$BeforeBreadcrumbCallback { - public abstract fun execute (Lio/sentry/Breadcrumb;Ljava/lang/Object;)Lio/sentry/Breadcrumb; + public abstract fun execute (Lio/sentry/Breadcrumb;Ljava/util/Map;)Lio/sentry/Breadcrumb; } public abstract interface class io/sentry/SentryOptions$BeforeSendCallback { - public abstract fun execute (Lio/sentry/SentryEvent;Ljava/lang/Object;)Lio/sentry/SentryEvent; + public abstract fun execute (Lio/sentry/SentryEvent;Ljava/util/Map;)Lio/sentry/SentryEvent; } public final class io/sentry/SentryOptions$Proxy { @@ -1481,6 +1481,43 @@ public abstract interface class io/sentry/TransactionFinishedCallback { public abstract fun execute (Lio/sentry/ITransaction;)V } +public final class io/sentry/TypeCheckHint { + public static final field ANDROID_ACTIVITY Ljava/lang/String; + public static final field ANDROID_CONFIGURATION Ljava/lang/String; + public static final field ANDROID_FRAGMENT Ljava/lang/String; + public static final field ANDROID_INTENT Ljava/lang/String; + public static final field ANDROID_MOTION_EVENT Ljava/lang/String; + public static final field ANDROID_SENSOR_EVENT Ljava/lang/String; + public static final field ANDROID_VIEW Ljava/lang/String; + public static final field APOLLO_REQUEST Ljava/lang/String; + public static final field APOLLO_RESPONSE Ljava/lang/String; + public static final field GRAPHQL_HANDLER_PARAMETERS Ljava/lang/String; + public static final field JUL_LOG_RECORD Ljava/lang/String; + public static final field LOG4J_LOG_EVENT Ljava/lang/String; + public static final field LOGBACK_LOGGING_EVENT Ljava/lang/String; + public static final field OKHTTP_REQUEST Ljava/lang/String; + public static final field OKHTTP_RESPONSE Ljava/lang/String; + public static final field OPEN_FEIGN_REQUEST Ljava/lang/String; + public static final field OPEN_FEIGN_RESPONSE Ljava/lang/String; + public static final field SENTRY_SYNTHETIC_EXCEPTION Ljava/lang/String; + public static final field SENTRY_TYPE_CHECK_HINT Ljava/lang/String; + public static final field SERVLET_REQUEST Ljava/lang/String; + public static final field SPRING_EXCHANGE_FILTER_REQUEST Ljava/lang/String; + public static final field SPRING_EXCHANGE_FILTER_RESPONSE Ljava/lang/String; + public static final field SPRING_REQUEST_FILTER_REQUEST Ljava/lang/String; + public static final field SPRING_REQUEST_FILTER_RESPONSE Ljava/lang/String; + public static final field SPRING_REQUEST_INTERCEPTOR_REQUEST Ljava/lang/String; + public static final field SPRING_REQUEST_INTERCEPTOR_REQUEST_BODY Ljava/lang/String; + public static final field SPRING_REQUEST_INTERCEPTOR_RESPONSE Ljava/lang/String; + public static final field SPRING_RESOLVER_REQUEST Ljava/lang/String; + public static final field SPRING_RESOLVER_RESPONSE Ljava/lang/String; + public static final field WEBFLUX_EXCEPTION_HANDLER_REQUEST Ljava/lang/String; + public static final field WEBFLUX_EXCEPTION_HANDLER_RESPONSE Ljava/lang/String; + public static final field WEBFLUX_FILTER_REQUEST Ljava/lang/String; + public static final field WEBFLUX_FILTER_RESPONSE Ljava/lang/String; + public fun ()V +} + public final class io/sentry/UncaughtExceptionHandlerIntegration : io/sentry/Integration, java/io/Closeable, java/lang/Thread$UncaughtExceptionHandler { public fun ()V public fun close ()V @@ -1527,13 +1564,13 @@ public final class io/sentry/cache/EnvelopeCache : io/sentry/cache/IEnvelopeCach public static fun create (Lio/sentry/SentryOptions;)Lio/sentry/cache/IEnvelopeCache; public fun discard (Lio/sentry/SentryEnvelope;)V public fun iterator ()Ljava/util/Iterator; - public fun store (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)V + public fun store (Lio/sentry/SentryEnvelope;Ljava/util/Map;)V } public abstract interface class io/sentry/cache/IEnvelopeCache : java/lang/Iterable { public abstract fun discard (Lio/sentry/SentryEnvelope;)V public fun store (Lio/sentry/SentryEnvelope;)V - public abstract fun store (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)V + public abstract fun store (Lio/sentry/SentryEnvelope;Ljava/util/Map;)V } public abstract interface class io/sentry/config/PropertiesProvider { @@ -2562,7 +2599,7 @@ public final class io/sentry/transport/AsyncHttpTransport : io/sentry/transport/ public fun (Lio/sentry/transport/QueuedThreadPoolExecutor;Lio/sentry/SentryOptions;Lio/sentry/transport/RateLimiter;Lio/sentry/transport/ITransportGate;Lio/sentry/transport/HttpConnection;)V public fun close ()V public fun flush (J)V - public fun send (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)V + public fun send (Lio/sentry/SentryEnvelope;Ljava/util/Map;)V } public final class io/sentry/transport/CurrentDateProvider : io/sentry/transport/ICurrentDateProvider { @@ -2577,7 +2614,7 @@ public abstract interface class io/sentry/transport/ICurrentDateProvider { public abstract interface class io/sentry/transport/ITransport : java/io/Closeable { public abstract fun flush (J)V public fun send (Lio/sentry/SentryEnvelope;)V - public abstract fun send (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)V + public abstract fun send (Lio/sentry/SentryEnvelope;Ljava/util/Map;)V } public abstract interface class io/sentry/transport/ITransportGate { @@ -2589,14 +2626,14 @@ public final class io/sentry/transport/NoOpEnvelopeCache : io/sentry/cache/IEnve public fun discard (Lio/sentry/SentryEnvelope;)V public static fun getInstance ()Lio/sentry/transport/NoOpEnvelopeCache; public fun iterator ()Ljava/util/Iterator; - public fun store (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)V + public fun store (Lio/sentry/SentryEnvelope;Ljava/util/Map;)V } public final class io/sentry/transport/NoOpTransport : io/sentry/transport/ITransport { public fun close ()V public fun flush (J)V public static fun getInstance ()Lio/sentry/transport/NoOpTransport; - public fun send (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)V + public fun send (Lio/sentry/SentryEnvelope;Ljava/util/Map;)V } public final class io/sentry/transport/NoOpTransportGate : io/sentry/transport/ITransportGate { @@ -2625,7 +2662,7 @@ public final class io/sentry/transport/StdoutTransport : io/sentry/transport/ITr public fun (Lio/sentry/ISerializer;)V public fun close ()V public fun flush (J)V - public fun send (Lio/sentry/SentryEnvelope;Ljava/lang/Object;)V + public fun send (Lio/sentry/SentryEnvelope;Ljava/util/Map;)V } public abstract class io/sentry/transport/TransportResult { @@ -2636,10 +2673,6 @@ public abstract class io/sentry/transport/TransportResult { public static fun success ()Lio/sentry/transport/TransportResult; } -public final class io/sentry/util/ApplyScopeUtils { - public static fun shouldApplyScopeData (Ljava/lang/Object;)Z -} - public final class io/sentry/util/CollectionUtils { public static fun filterMapEntries (Ljava/util/Map;Lio/sentry/util/CollectionUtils$Predicate;)Ljava/util/Map; public static fun newArrayList (Ljava/util/List;)Ljava/util/List; @@ -2657,6 +2690,11 @@ public final class io/sentry/util/ExceptionUtils { public static fun findRootCause (Ljava/lang/Throwable;)Ljava/lang/Throwable; } +public final class io/sentry/util/HintUtils { + public static fun getSentrySdkHint (Ljava/util/Map;)Ljava/lang/Object; + public static fun shouldApplyScopeData (Ljava/util/Map;)Z +} + public final class io/sentry/util/LogUtils { public fun ()V public static fun logIfNotFlushable (Lio/sentry/ILogger;Ljava/lang/Object;)V diff --git a/sentry/src/main/java/io/sentry/DirectoryProcessor.java b/sentry/src/main/java/io/sentry/DirectoryProcessor.java index 248531aa5b5..3277715021c 100644 --- a/sentry/src/main/java/io/sentry/DirectoryProcessor.java +++ b/sentry/src/main/java/io/sentry/DirectoryProcessor.java @@ -1,12 +1,15 @@ package io.sentry; import static io.sentry.SentryLevel.ERROR; +import static io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT; import io.sentry.hints.Cached; import io.sentry.hints.Flushable; import io.sentry.hints.Retryable; import io.sentry.hints.SubmissionResult; import java.io.File; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.jetbrains.annotations.NotNull; @@ -63,14 +66,19 @@ public void processDirectory(final @NotNull File directory) { logger.log(SentryLevel.DEBUG, "Processing file: %s", file.getAbsolutePath()); final SendCachedEnvelopeHint hint = new SendCachedEnvelopeHint(flushTimeoutMillis, logger); - processFile(file, hint); + + final Map hintMap = new HashMap<>(); + hintMap.put(SENTRY_TYPE_CHECK_HINT, hint); + + processFile(file, hintMap); } } catch (Throwable e) { logger.log(SentryLevel.ERROR, e, "Failed processing '%s'", directory.getAbsolutePath()); } } - protected abstract void processFile(final @NotNull File file, final @Nullable Object hint); + protected abstract void processFile( + final @NotNull File file, final @Nullable Map hint); protected abstract boolean isRelevantFileName(String fileName); diff --git a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java index e5888eaadf5..a5baa3c5fc6 100644 --- a/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java +++ b/sentry/src/main/java/io/sentry/DuplicateEventDetectionEventProcessor.java @@ -21,7 +21,7 @@ public DuplicateEventDetectionEventProcessor(final @NotNull SentryOptions option @Override public @Nullable SentryEvent process( - final @NotNull SentryEvent event, final @Nullable Object hint) { + final @NotNull SentryEvent event, final @Nullable Map hint) { if (options.isEnableDeduplication()) { final Throwable throwable = event.getThrowable(); if (throwable != null) { diff --git a/sentry/src/main/java/io/sentry/EnvelopeSender.java b/sentry/src/main/java/io/sentry/EnvelopeSender.java index 882d85cf47c..bae79a69979 100644 --- a/sentry/src/main/java/io/sentry/EnvelopeSender.java +++ b/sentry/src/main/java/io/sentry/EnvelopeSender.java @@ -3,6 +3,7 @@ import io.sentry.cache.EnvelopeCache; import io.sentry.hints.Flushable; import io.sentry.hints.Retryable; +import io.sentry.util.HintUtils; import io.sentry.util.LogUtils; import io.sentry.util.Objects; import java.io.BufferedInputStream; @@ -11,6 +12,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,7 +36,7 @@ public EnvelopeSender( } @Override - protected void processFile(final @NotNull File file, final @Nullable Object hint) { + protected void processFile(final @NotNull File file, final @Nullable Map hint) { if (!file.isFile()) { logger.log(SentryLevel.DEBUG, "'%s' is not a file.", file.getAbsolutePath()); return; @@ -54,6 +56,8 @@ protected void processFile(final @NotNull File file, final @Nullable Object hint return; } + Object sentrySdkHint = HintUtils.getSentrySdkHint(hint); + try (final InputStream is = new BufferedInputStream(new FileInputStream(file))) { SentryEnvelope envelope = serializer.deserializeEnvelope(is); if (envelope == null) { @@ -63,12 +67,12 @@ protected void processFile(final @NotNull File file, final @Nullable Object hint hub.captureEnvelope(envelope, hint); } - if (hint instanceof Flushable) { - if (!((Flushable) hint).waitFlush()) { + if (sentrySdkHint instanceof Flushable) { + if (!((Flushable) sentrySdkHint).waitFlush()) { logger.log(SentryLevel.WARNING, "Timed out waiting for envelope submission."); } } else { - LogUtils.logIfNotFlushable(logger, hint); + LogUtils.logIfNotFlushable(logger, sentrySdkHint); } } catch (FileNotFoundException e) { logger.log(SentryLevel.ERROR, e, "File '%s' cannot be found.", file.getAbsolutePath()); @@ -77,16 +81,16 @@ protected void processFile(final @NotNull File file, final @Nullable Object hint } catch (Throwable e) { logger.log( SentryLevel.ERROR, e, "Failed to capture cached envelope %s", file.getAbsolutePath()); - if (hint instanceof Retryable) { - ((Retryable) hint).setRetry(false); + if (sentrySdkHint instanceof Retryable) { + ((Retryable) sentrySdkHint).setRetry(false); logger.log(SentryLevel.INFO, e, "File '%s' won't retry.", file.getAbsolutePath()); } else { - LogUtils.logIfNotRetryable(logger, hint); + LogUtils.logIfNotRetryable(logger, sentrySdkHint); } } finally { // Unless the transport marked this to be retried, it'll be deleted. - if (hint instanceof Retryable) { - if (!((Retryable) hint).isRetry()) { + if (sentrySdkHint instanceof Retryable) { + if (!((Retryable) sentrySdkHint).isRetry()) { safeDelete(file, "after trying to capture it"); logger.log(SentryLevel.DEBUG, "Deleted file %s.", file.getAbsolutePath()); } else { @@ -96,7 +100,7 @@ protected void processFile(final @NotNull File file, final @Nullable Object hint file.getAbsolutePath()); } } else { - LogUtils.logIfNotRetryable(logger, hint); + LogUtils.logIfNotRetryable(logger, sentrySdkHint); } } } @@ -107,7 +111,8 @@ protected boolean isRelevantFileName(final @NotNull String fileName) { } @Override - public void processEnvelopeFile(final @NotNull String path, final @Nullable Object hint) { + public void processEnvelopeFile( + final @NotNull String path, final @Nullable Map hint) { Objects.requireNonNull(path, "Path is required."); processFile(new File(path), hint); diff --git a/sentry/src/main/java/io/sentry/EventProcessor.java b/sentry/src/main/java/io/sentry/EventProcessor.java index d5f601f4307..8f4a3b2cd40 100644 --- a/sentry/src/main/java/io/sentry/EventProcessor.java +++ b/sentry/src/main/java/io/sentry/EventProcessor.java @@ -1,6 +1,7 @@ package io.sentry; import io.sentry.protocol.SentryTransaction; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -17,7 +18,7 @@ public interface EventProcessor { * @return the event itself, a mutated SentryEvent or null */ @Nullable - default SentryEvent process(@NotNull SentryEvent event, @Nullable Object hint) { + default SentryEvent process(@NotNull SentryEvent event, @Nullable Map hint) { return event; } @@ -29,7 +30,8 @@ default SentryEvent process(@NotNull SentryEvent event, @Nullable Object hint) { * @return the event itself, a mutated SentryTransaction or null */ @Nullable - default SentryTransaction process(@NotNull SentryTransaction transaction, @Nullable Object hint) { + default SentryTransaction process( + @NotNull SentryTransaction transaction, @Nullable Map hint) { return transaction; } } diff --git a/sentry/src/main/java/io/sentry/Hub.java b/sentry/src/main/java/io/sentry/Hub.java index 56309475ced..e7c1d9febed 100644 --- a/sentry/src/main/java/io/sentry/Hub.java +++ b/sentry/src/main/java/io/sentry/Hub.java @@ -1,5 +1,7 @@ package io.sentry; +import static io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT; + import io.sentry.Stack.StackItem; import io.sentry.hints.SessionEndHint; import io.sentry.hints.SessionStartHint; @@ -12,6 +14,7 @@ import java.io.Closeable; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.WeakHashMap; @@ -73,7 +76,7 @@ public boolean isEnabled() { @Override public @NotNull SentryId captureEvent( - final @NotNull SentryEvent event, final @Nullable Object hint) { + final @NotNull SentryEvent event, final @Nullable Map hint) { SentryId sentryId = SentryId.EMPTY_ID; if (!isEnabled()) { options @@ -125,7 +128,7 @@ public boolean isEnabled() { @ApiStatus.Internal @Override public @NotNull SentryId captureEnvelope( - final @NotNull SentryEnvelope envelope, final @Nullable Object hint) { + final @NotNull SentryEnvelope envelope, final @Nullable Map hint) { Objects.requireNonNull(envelope, "SentryEnvelope is required."); SentryId sentryId = SentryId.EMPTY_ID; @@ -151,7 +154,7 @@ public boolean isEnabled() { @Override public @NotNull SentryId captureException( - final @NotNull Throwable throwable, final @Nullable Object hint) { + final @NotNull Throwable throwable, final @Nullable Map hint) { SentryId sentryId = SentryId.EMPTY_ID; if (!isEnabled()) { options @@ -233,10 +236,16 @@ public void startSession() { // single envelope // Or create the envelope here with both items and call `captureEnvelope` if (pair.getPrevious() != null) { - item.getClient().captureSession(pair.getPrevious(), new SessionEndHint()); + final Map hintMap = new HashMap<>(); + hintMap.put(SENTRY_TYPE_CHECK_HINT, new SessionEndHint()); + + item.getClient().captureSession(pair.getPrevious(), hintMap); } - item.getClient().captureSession(pair.getCurrent(), new SessionStartHint()); + final Map hintMap = new HashMap<>(); + hintMap.put(SENTRY_TYPE_CHECK_HINT, new SessionStartHint()); + + item.getClient().captureSession(pair.getCurrent(), hintMap); } else { options.getLogger().log(SentryLevel.WARNING, "Session could not be started."); } @@ -253,7 +262,10 @@ public void endSession() { final StackItem item = this.stack.peek(); final Session previousSession = item.getScope().endSession(); if (previousSession != null) { - item.getClient().captureSession(previousSession, new SessionEndHint()); + final Map hintMap = new HashMap<>(); + hintMap.put(SENTRY_TYPE_CHECK_HINT, new SessionEndHint()); + + item.getClient().captureSession(previousSession, hintMap); } } } @@ -285,7 +297,8 @@ public void close() { } @Override - public void addBreadcrumb(final @NotNull Breadcrumb breadcrumb, final @Nullable Object hint) { + public void addBreadcrumb( + final @NotNull Breadcrumb breadcrumb, final @Nullable Map hint) { if (!isEnabled()) { options .getLogger() @@ -538,7 +551,7 @@ public void flush(long timeoutMillis) { public @NotNull SentryId captureTransaction( final @NotNull SentryTransaction transaction, final @Nullable TraceState traceState, - final @Nullable Object hint) { + final @Nullable Map hint) { Objects.requireNonNull(transaction, "transaction is required"); SentryId sentryId = SentryId.EMPTY_ID; diff --git a/sentry/src/main/java/io/sentry/HubAdapter.java b/sentry/src/main/java/io/sentry/HubAdapter.java index b0fd237fed4..ec689086c31 100644 --- a/sentry/src/main/java/io/sentry/HubAdapter.java +++ b/sentry/src/main/java/io/sentry/HubAdapter.java @@ -5,6 +5,7 @@ import io.sentry.protocol.User; import java.util.Date; import java.util.List; +import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -25,7 +26,8 @@ public boolean isEnabled() { } @Override - public @NotNull SentryId captureEvent(@NotNull SentryEvent event, @Nullable Object hint) { + public @NotNull SentryId captureEvent( + @NotNull SentryEvent event, @Nullable Map hint) { return Sentry.captureEvent(event, hint); } @@ -37,12 +39,13 @@ public boolean isEnabled() { @ApiStatus.Internal @Override public @NotNull SentryId captureEnvelope( - @NotNull SentryEnvelope envelope, @Nullable Object hint) { + @NotNull SentryEnvelope envelope, @Nullable Map hint) { return Sentry.getCurrentHub().captureEnvelope(envelope, hint); } @Override - public @NotNull SentryId captureException(@NotNull Throwable throwable, @Nullable Object hint) { + public @NotNull SentryId captureException( + @NotNull Throwable throwable, @Nullable Map hint) { return Sentry.captureException(throwable, hint); } @@ -67,7 +70,7 @@ public void close() { } @Override - public void addBreadcrumb(@NotNull Breadcrumb breadcrumb, @Nullable Object hint) { + public void addBreadcrumb(@NotNull Breadcrumb breadcrumb, @Nullable Map hint) { Sentry.addBreadcrumb(breadcrumb, hint); } @@ -160,7 +163,7 @@ public void flush(long timeoutMillis) { public @NotNull SentryId captureTransaction( @NotNull SentryTransaction transaction, @Nullable TraceState traceState, - @Nullable Object hint) { + @Nullable Map hint) { return Sentry.getCurrentHub().captureTransaction(transaction, traceState, hint); } diff --git a/sentry/src/main/java/io/sentry/IEnvelopeSender.java b/sentry/src/main/java/io/sentry/IEnvelopeSender.java index 2e203e03913..2a346e7400f 100644 --- a/sentry/src/main/java/io/sentry/IEnvelopeSender.java +++ b/sentry/src/main/java/io/sentry/IEnvelopeSender.java @@ -1,8 +1,9 @@ package io.sentry; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface IEnvelopeSender { - void processEnvelopeFile(@NotNull String path, @Nullable Object hint); + void processEnvelopeFile(@NotNull String path, @Nullable Map hint); } diff --git a/sentry/src/main/java/io/sentry/IHub.java b/sentry/src/main/java/io/sentry/IHub.java index 78ba3751e13..21717524c12 100644 --- a/sentry/src/main/java/io/sentry/IHub.java +++ b/sentry/src/main/java/io/sentry/IHub.java @@ -5,6 +5,7 @@ import io.sentry.protocol.User; import java.util.Date; import java.util.List; +import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,7 +28,7 @@ public interface IHub { * @return The Id (SentryId object) of the event */ @NotNull - SentryId captureEvent(@NotNull SentryEvent event, @Nullable Object hint); + SentryId captureEvent(@NotNull SentryEvent event, @Nullable Map hint); /** * Captures the event. @@ -67,7 +68,7 @@ public interface IHub { * @return The Id (SentryId object) of the event */ @NotNull - SentryId captureEnvelope(@NotNull SentryEnvelope envelope, @Nullable Object hint); + SentryId captureEnvelope(@NotNull SentryEnvelope envelope, @Nullable Map hint); /** * Captures an envelope. @@ -87,7 +88,7 @@ public interface IHub { * @return The Id (SentryId object) of the event */ @NotNull - SentryId captureException(@NotNull Throwable throwable, @Nullable Object hint); + SentryId captureException(@NotNull Throwable throwable, @Nullable Map hint); /** * Captures the exception. @@ -121,7 +122,7 @@ public interface IHub { * @param breadcrumb the breadcrumb * @param hint SDK specific but provides high level information about the origin of the event */ - void addBreadcrumb(@NotNull Breadcrumb breadcrumb, @Nullable Object hint); + void addBreadcrumb(@NotNull Breadcrumb breadcrumb, @Nullable Map hint); /** * Adds a breadcrumb to the current Scope @@ -279,12 +280,12 @@ default void addBreadcrumb(@NotNull String message, @NotNull String category) { SentryId captureTransaction( @NotNull SentryTransaction transaction, @Nullable TraceState traceState, - @Nullable Object hint); + @Nullable Map hint); @ApiStatus.Internal @NotNull default SentryId captureTransaction( - @NotNull SentryTransaction transaction, @Nullable Object hint) { + @NotNull SentryTransaction transaction, @Nullable Map hint) { return captureTransaction(transaction, null, hint); } diff --git a/sentry/src/main/java/io/sentry/ISentryClient.java b/sentry/src/main/java/io/sentry/ISentryClient.java index b8273d3f8e8..e6d73f9ef15 100644 --- a/sentry/src/main/java/io/sentry/ISentryClient.java +++ b/sentry/src/main/java/io/sentry/ISentryClient.java @@ -3,6 +3,7 @@ import io.sentry.protocol.Message; import io.sentry.protocol.SentryId; import io.sentry.protocol.SentryTransaction; +import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,7 +27,8 @@ public interface ISentryClient { * @return The Id (SentryId object) of the event. */ @NotNull - SentryId captureEvent(@NotNull SentryEvent event, @Nullable Scope scope, @Nullable Object hint); + SentryId captureEvent( + @NotNull SentryEvent event, @Nullable Scope scope, @Nullable Map hint); /** Flushes out the queue for up to timeout seconds and disable the client. */ void close(); @@ -66,7 +68,8 @@ public interface ISentryClient { * @param hint SDK specific but provides high level information about the origin of the event. * @return The Id (SentryId object) of the event. */ - default @NotNull SentryId captureEvent(@NotNull SentryEvent event, @Nullable Object hint) { + default @NotNull SentryId captureEvent( + @NotNull SentryEvent event, @Nullable Map hint) { return captureEvent(event, null, hint); } @@ -119,7 +122,7 @@ public interface ISentryClient { * @return The Id (SentryId object) of the event */ default @NotNull SentryId captureException( - @NotNull Throwable throwable, @Nullable Scope scope, @Nullable Object hint) { + @NotNull Throwable throwable, @Nullable Scope scope, @Nullable Map hint) { SentryEvent event = new SentryEvent(throwable); return captureEvent(event, scope, hint); } @@ -131,7 +134,8 @@ public interface ISentryClient { * @param hint SDK specific but provides high level information about the origin of the event * @return The Id (SentryId object) of the event */ - default @NotNull SentryId captureException(@NotNull Throwable throwable, @Nullable Object hint) { + default @NotNull SentryId captureException( + @NotNull Throwable throwable, @Nullable Map hint) { return captureException(throwable, null, hint); } @@ -160,7 +164,7 @@ public interface ISentryClient { * @param hint SDK specific but provides high level information about the origin of the event * @param session the Session */ - void captureSession(@NotNull Session session, @Nullable Object hint); + void captureSession(@NotNull Session session, @Nullable Map hint); /** * Captures a session. This method transform a session to an envelope and forwards to @@ -180,7 +184,7 @@ default void captureSession(@NotNull Session session) { * @return The Id (SentryId object) of the event */ @Nullable - SentryId captureEnvelope(@NotNull SentryEnvelope envelope, @Nullable Object hint); + SentryId captureEnvelope(@NotNull SentryEnvelope envelope, @Nullable Map hint); /** * Captures an envelope. @@ -202,7 +206,9 @@ default void captureSession(@NotNull Session session) { */ @NotNull default SentryId captureTransaction( - @NotNull SentryTransaction transaction, @Nullable Scope scope, @Nullable Object hint) { + @NotNull SentryTransaction transaction, + @Nullable Scope scope, + @Nullable Map hint) { return captureTransaction(transaction, null, scope, hint); } @@ -221,7 +227,7 @@ SentryId captureTransaction( @NotNull SentryTransaction transaction, @Nullable TraceState traceState, @Nullable Scope scope, - @Nullable Object hint); + @Nullable Map hint); /** * Captures a transaction without scope nor hint. diff --git a/sentry/src/main/java/io/sentry/MainEventProcessor.java b/sentry/src/main/java/io/sentry/MainEventProcessor.java index 72372c6d873..72dd924a2d6 100644 --- a/sentry/src/main/java/io/sentry/MainEventProcessor.java +++ b/sentry/src/main/java/io/sentry/MainEventProcessor.java @@ -6,7 +6,7 @@ import io.sentry.protocol.SentryException; import io.sentry.protocol.SentryTransaction; import io.sentry.protocol.User; -import io.sentry.util.ApplyScopeUtils; +import io.sentry.util.HintUtils; import io.sentry.util.Objects; import java.io.Closeable; import java.io.IOException; @@ -65,7 +65,7 @@ public final class MainEventProcessor implements EventProcessor, Closeable { @Override public @NotNull SentryEvent process( - final @NotNull SentryEvent event, final @Nullable Object hint) { + final @NotNull SentryEvent event, final @Nullable Map hint) { setCommons(event); setExceptions(event); setDebugMeta(event); @@ -100,8 +100,8 @@ private void setDebugMeta(final @NotNull SentryEvent event) { } private boolean shouldApplyScopeData( - final @NotNull SentryBaseEvent event, final @Nullable Object hint) { - if (ApplyScopeUtils.shouldApplyScopeData(hint)) { + final @NotNull SentryBaseEvent event, final @Nullable Map hint) { + if (HintUtils.shouldApplyScopeData(hint)) { return true; } else { options @@ -126,7 +126,7 @@ private void processNonCachedEvent(final @NotNull SentryBaseEvent event) { @Override public @NotNull SentryTransaction process( - final @NotNull SentryTransaction transaction, final @Nullable Object hint) { + final @NotNull SentryTransaction transaction, final @Nullable Map hint) { setCommons(transaction); if (shouldApplyScopeData(transaction, hint)) { @@ -213,7 +213,8 @@ private void setExceptions(final @NotNull SentryEvent event) { } } - private void setThreads(final @NotNull SentryEvent event, final @Nullable Object hint) { + private void setThreads( + final @NotNull SentryEvent event, final @Nullable Map hint) { if (event.getThreads() == null) { // collecting threadIds that came from the exception mechanism, so we can mark threads as // crashed properly @@ -232,11 +233,12 @@ private void setThreads(final @NotNull SentryEvent event, final @Nullable Object } } + Object sentrySdkHint = HintUtils.getSentrySdkHint(hint); if (options.isAttachThreads()) { event.setThreads(sentryThreadFactory.getCurrentThreads(mechanismThreadIds)); } else if (options.isAttachStacktrace() && (eventExceptions == null || eventExceptions.isEmpty()) - && !isCachedHint(hint)) { + && !isCachedHint(sentrySdkHint)) { // when attachStacktrace is enabled, we attach only the current thread and its stack traces, // if there are no exceptions, exceptions have its own stack traces. event.setThreads(sentryThreadFactory.getCurrentThread()); @@ -248,11 +250,11 @@ private void setThreads(final @NotNull SentryEvent event, final @Nullable Object * If the event has a Cached Hint, it means that it came from the EnvelopeFileObserver. We don't * want to append the current thread to the event. * - * @param hint the Hint + * @param sentrySdkHint the Hint * @return true if Cached or false otherwise */ - private boolean isCachedHint(final @Nullable Object hint) { - return (hint instanceof Cached); + private boolean isCachedHint(final @Nullable Object sentrySdkHint) { + return (sentrySdkHint instanceof Cached); } @Override diff --git a/sentry/src/main/java/io/sentry/NoOpHub.java b/sentry/src/main/java/io/sentry/NoOpHub.java index 728e6f5b632..d8745cb3c2f 100644 --- a/sentry/src/main/java/io/sentry/NoOpHub.java +++ b/sentry/src/main/java/io/sentry/NoOpHub.java @@ -5,6 +5,7 @@ import io.sentry.protocol.User; import java.util.Date; import java.util.List; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,7 +27,8 @@ public boolean isEnabled() { } @Override - public @NotNull SentryId captureEvent(@NotNull SentryEvent event, @Nullable Object hint) { + public @NotNull SentryId captureEvent( + @NotNull SentryEvent event, @Nullable Map hint) { return SentryId.EMPTY_ID; } @@ -37,12 +39,13 @@ public boolean isEnabled() { @Override public @NotNull SentryId captureEnvelope( - @NotNull SentryEnvelope envelope, @Nullable Object hint) { + @NotNull SentryEnvelope envelope, @Nullable Map hint) { return SentryId.EMPTY_ID; } @Override - public @NotNull SentryId captureException(@NotNull Throwable throwable, @Nullable Object hint) { + public @NotNull SentryId captureException( + @NotNull Throwable throwable, @Nullable Map hint) { return SentryId.EMPTY_ID; } @@ -59,7 +62,7 @@ public void endSession() {} public void close() {} @Override - public void addBreadcrumb(@NotNull Breadcrumb breadcrumb, @Nullable Object hint) {} + public void addBreadcrumb(@NotNull Breadcrumb breadcrumb, @Nullable Map hint) {} @Override public void setLevel(@Nullable SentryLevel level) {} @@ -120,7 +123,7 @@ public void flush(long timeoutMillis) {} public @NotNull SentryId captureTransaction( final @NotNull SentryTransaction transaction, final @Nullable TraceState traceState, - final @Nullable Object hint) { + final @Nullable Map hint) { return SentryId.EMPTY_ID; } diff --git a/sentry/src/main/java/io/sentry/NoOpSentryClient.java b/sentry/src/main/java/io/sentry/NoOpSentryClient.java index aace30692b4..c3fccb0d77c 100644 --- a/sentry/src/main/java/io/sentry/NoOpSentryClient.java +++ b/sentry/src/main/java/io/sentry/NoOpSentryClient.java @@ -2,6 +2,7 @@ import io.sentry.protocol.SentryId; import io.sentry.protocol.SentryTransaction; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -22,7 +23,7 @@ public boolean isEnabled() { @Override public @NotNull SentryId captureEvent( - @NotNull SentryEvent event, @Nullable Scope scope, @Nullable Object hint) { + @NotNull SentryEvent event, @Nullable Scope scope, @Nullable Map hint) { return SentryId.EMPTY_ID; } @@ -36,10 +37,11 @@ public void flush(long timeoutMillis) {} public void captureUserFeedback(@NotNull UserFeedback userFeedback) {} @Override - public void captureSession(@NotNull Session session, @Nullable Object hint) {} + public void captureSession(@NotNull Session session, @Nullable Map hint) {} @Override - public SentryId captureEnvelope(@NotNull SentryEnvelope envelope, @Nullable Object hint) { + public SentryId captureEnvelope( + @NotNull SentryEnvelope envelope, @Nullable Map hint) { return SentryId.EMPTY_ID; } @@ -48,7 +50,7 @@ public SentryId captureEnvelope(@NotNull SentryEnvelope envelope, @Nullable Obje @NotNull SentryTransaction transaction, @Nullable TraceState traceState, @Nullable Scope scope, - @Nullable Object hint) { + @Nullable Map hint) { return SentryId.EMPTY_ID; } } diff --git a/sentry/src/main/java/io/sentry/OutboxSender.java b/sentry/src/main/java/io/sentry/OutboxSender.java index 0631a19e317..5f9529292c1 100644 --- a/sentry/src/main/java/io/sentry/OutboxSender.java +++ b/sentry/src/main/java/io/sentry/OutboxSender.java @@ -10,6 +10,7 @@ import io.sentry.protocol.SentryId; import io.sentry.protocol.SentryTransaction; import io.sentry.util.CollectionUtils; +import io.sentry.util.HintUtils; import io.sentry.util.LogUtils; import io.sentry.util.Objects; import java.io.BufferedInputStream; @@ -22,6 +23,7 @@ import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.Charset; +import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,7 +53,7 @@ public OutboxSender( } @Override - protected void processFile(final @NotNull File file, @Nullable Object hint) { + protected void processFile(final @NotNull File file, @Nullable Map hint) { Objects.requireNonNull(file, "File is required."); if (!isRelevantFileName(file.getName())) { @@ -59,6 +61,8 @@ protected void processFile(final @NotNull File file, @Nullable Object hint) { return; } + Object sentrySdkHint = HintUtils.getSentrySdkHint(hint); + try (final InputStream stream = new BufferedInputStream(new FileInputStream(file))) { final SentryEnvelope envelope = envelopeReader.read(stream); if (envelope == null) { @@ -73,8 +77,8 @@ protected void processFile(final @NotNull File file, @Nullable Object hint) { } catch (IOException e) { logger.log(SentryLevel.ERROR, "Error processing envelope.", e); } finally { - if (hint instanceof Retryable) { - if (!((Retryable) hint).isRetry()) { + if (sentrySdkHint instanceof Retryable) { + if (!((Retryable) sentrySdkHint).isRetry()) { try { if (!file.delete()) { logger.log(SentryLevel.ERROR, "Failed to delete: %s", file.getAbsolutePath()); @@ -84,7 +88,7 @@ protected void processFile(final @NotNull File file, @Nullable Object hint) { } } } else { - LogUtils.logIfNotRetryable(logger, hint); + LogUtils.logIfNotRetryable(logger, sentrySdkHint); } } } @@ -97,13 +101,14 @@ protected boolean isRelevantFileName(final @Nullable String fileName) { } @Override - public void processEnvelopeFile(@NotNull String path, @Nullable Object hint) { + public void processEnvelopeFile(@NotNull String path, @Nullable Map hint) { Objects.requireNonNull(path, "Path is required."); processFile(new File(path), hint); } - private void processEnvelope(final @NotNull SentryEnvelope envelope, final @Nullable Object hint) + private void processEnvelope( + final @NotNull SentryEnvelope envelope, final @Nullable Map hint) throws IOException { logger.log( SentryLevel.DEBUG, @@ -111,6 +116,8 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @Null CollectionUtils.size(envelope.getItems())); int currentItem = 0; + Object sentrySdkHint = HintUtils.getSentrySdkHint(hint); + for (final SentryEnvelopeItem item : envelope.getItems()) { currentItem++; @@ -134,7 +141,7 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @Null hub.captureEvent(event, hint); logItemCaptured(currentItem); - if (!waitFlush(hint)) { + if (!waitFlush(sentrySdkHint)) { logTimeout(event.getEventId()); break; } @@ -166,7 +173,7 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @Null hub.captureTransaction(transaction, envelope.getHeader().getTrace(), hint); logItemCaptured(currentItem); - if (!waitFlush(hint)) { + if (!waitFlush(sentrySdkHint)) { logTimeout(transaction.getEventId()); break; } @@ -186,7 +193,7 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @Null item.getHeader().getType().getItemType(), currentItem); - if (!waitFlush(hint)) { + if (!waitFlush(sentrySdkHint)) { logger.log( SentryLevel.WARNING, "Timed out waiting for item type submission: %s", @@ -195,8 +202,8 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @Null } } - if (hint instanceof SubmissionResult) { - if (!((SubmissionResult) hint).isSuccess()) { + if (sentrySdkHint instanceof SubmissionResult) { + if (!((SubmissionResult) sentrySdkHint).isSuccess()) { // Failed to send an item of the envelope: Stop attempting to send the rest (an attachment // without the event that created it isn't useful) logger.log( @@ -208,8 +215,8 @@ private void processEnvelope(final @NotNull SentryEnvelope envelope, final @Null } // reset the Hint to its initial state as we use it multiple times. - if (hint instanceof Resettable) { - ((Resettable) hint).reset(); + if (sentrySdkHint instanceof Resettable) { + ((Resettable) sentrySdkHint).reset(); } } } @@ -240,11 +247,11 @@ private void logTimeout(final @Nullable SentryId eventId) { logger.log(SentryLevel.WARNING, "Timed out waiting for event id submission: %s", eventId); } - private boolean waitFlush(final @Nullable Object hint) { - if (hint instanceof Flushable) { - return ((Flushable) hint).waitFlush(); + private boolean waitFlush(final @Nullable Object sentrySdkHint) { + if (sentrySdkHint instanceof Flushable) { + return ((Flushable) sentrySdkHint).waitFlush(); } else { - LogUtils.logIfNotFlushable(logger, hint); + LogUtils.logIfNotFlushable(logger, sentrySdkHint); } return true; } diff --git a/sentry/src/main/java/io/sentry/Scope.java b/sentry/src/main/java/io/sentry/Scope.java index 1c4ff1a2774..6ee070f6c84 100644 --- a/sentry/src/main/java/io/sentry/Scope.java +++ b/sentry/src/main/java/io/sentry/Scope.java @@ -294,7 +294,7 @@ Queue getBreadcrumbs() { private @Nullable Breadcrumb executeBeforeBreadcrumb( final @NotNull SentryOptions.BeforeBreadcrumbCallback callback, @NotNull Breadcrumb breadcrumb, - final @Nullable Object hint) { + final @Nullable Map hint) { try { breadcrumb = callback.execute(breadcrumb, hint); } catch (Throwable e) { @@ -319,7 +319,8 @@ Queue getBreadcrumbs() { * @param breadcrumb the breadcrumb * @param hint the hint */ - public void addBreadcrumb(@NotNull Breadcrumb breadcrumb, final @Nullable Object hint) { + public void addBreadcrumb( + @NotNull Breadcrumb breadcrumb, final @Nullable Map hint) { if (breadcrumb == null) { return; } diff --git a/sentry/src/main/java/io/sentry/Sentry.java b/sentry/src/main/java/io/sentry/Sentry.java index c2c5980b6eb..fe2c2d6ff4c 100644 --- a/sentry/src/main/java/io/sentry/Sentry.java +++ b/sentry/src/main/java/io/sentry/Sentry.java @@ -8,6 +8,7 @@ import java.lang.reflect.InvocationTargetException; import java.util.Date; import java.util.List; +import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -260,7 +261,7 @@ public static synchronized void close() { * @return The Id (SentryId object) of the event */ public static @NotNull SentryId captureEvent( - final @NotNull SentryEvent event, final @Nullable Object hint) { + final @NotNull SentryEvent event, final @Nullable Map hint) { return getCurrentHub().captureEvent(event, hint); } @@ -304,7 +305,7 @@ public static synchronized void close() { * @return The Id (SentryId object) of the event */ public static @NotNull SentryId captureException( - final @NotNull Throwable throwable, final @Nullable Object hint) { + final @NotNull Throwable throwable, final @Nullable Map hint) { return getCurrentHub().captureException(throwable, hint); } @@ -324,7 +325,7 @@ public static void captureUserFeedback(final @NotNull UserFeedback userFeedback) * @param hint SDK specific but provides high level information about the origin of the event */ public static void addBreadcrumb( - final @NotNull Breadcrumb breadcrumb, final @Nullable Object hint) { + final @NotNull Breadcrumb breadcrumb, final @Nullable Map hint) { getCurrentHub().addBreadcrumb(breadcrumb, hint); } diff --git a/sentry/src/main/java/io/sentry/SentryClient.java b/sentry/src/main/java/io/sentry/SentryClient.java index d69ea363230..76bef2a030e 100644 --- a/sentry/src/main/java/io/sentry/SentryClient.java +++ b/sentry/src/main/java/io/sentry/SentryClient.java @@ -5,7 +5,7 @@ import io.sentry.protocol.SentryId; import io.sentry.protocol.SentryTransaction; import io.sentry.transport.ITransport; -import io.sentry.util.ApplyScopeUtils; +import io.sentry.util.HintUtils; import io.sentry.util.Objects; import java.io.Closeable; import java.io.IOException; @@ -55,8 +55,8 @@ public boolean isEnabled() { } private boolean shouldApplyScopeData( - final @NotNull SentryBaseEvent event, final @Nullable Object hint) { - if (ApplyScopeUtils.shouldApplyScopeData(hint)) { + final @NotNull SentryBaseEvent event, final @Nullable Map hint) { + if (HintUtils.shouldApplyScopeData(hint)) { return true; } else { options @@ -68,7 +68,9 @@ private boolean shouldApplyScopeData( @Override public @NotNull SentryId captureEvent( - @NotNull SentryEvent event, final @Nullable Scope scope, final @Nullable Object hint) { + @NotNull SentryEvent event, + final @Nullable Scope scope, + final @Nullable Map hint) { Objects.requireNonNull(event, "SentryEvent is required."); options.getLogger().log(SentryLevel.DEBUG, "Capturing event: %s", event.getEventId()); @@ -199,7 +201,7 @@ private boolean shouldApplyScopeData( @Nullable private SentryEvent processEvent( @NotNull SentryEvent event, - final @Nullable Object hint, + final @Nullable Map hint, final @NotNull List eventProcessors) { for (final EventProcessor processor : eventProcessors) { try { @@ -230,7 +232,7 @@ private SentryEvent processEvent( @Nullable private SentryTransaction processTransaction( @NotNull SentryTransaction transaction, - final @Nullable Object hint, + final @Nullable Map hint, final @NotNull List eventProcessors) { for (final EventProcessor processor : eventProcessors) { try { @@ -307,10 +309,12 @@ public void captureUserFeedback(final @NotNull UserFeedback userFeedback) { @TestOnly @Nullable Session updateSessionData( - final @NotNull SentryEvent event, final @Nullable Object hint, final @Nullable Scope scope) { + final @NotNull SentryEvent event, + final @Nullable Map hint, + final @Nullable Scope scope) { Session clonedSession = null; - if (ApplyScopeUtils.shouldApplyScopeData(hint)) { + if (HintUtils.shouldApplyScopeData(hint)) { if (scope != null) { clonedSession = scope.withSession( @@ -334,9 +338,10 @@ Session updateSessionData( } if (session.update(status, userAgent, crashedOrErrored)) { + Object sentrySdkHint = HintUtils.getSentrySdkHint(hint); // if hint is DiskFlushNotification, it means we have an uncaughtException // and we can end the session. - if (hint instanceof DiskFlushNotification) { + if (sentrySdkHint instanceof DiskFlushNotification) { session.end(); } } @@ -355,7 +360,8 @@ Session updateSessionData( @ApiStatus.Internal @Override - public void captureSession(final @NotNull Session session, final @Nullable Object hint) { + public void captureSession( + final @NotNull Session session, final @Nullable Map hint) { Objects.requireNonNull(session, "Session is required."); if (session.getRelease() == null || session.getRelease().isEmpty()) { @@ -379,7 +385,7 @@ public void captureSession(final @NotNull Session session, final @Nullable Objec @ApiStatus.Internal @Override public @NotNull SentryId captureEnvelope( - final @NotNull SentryEnvelope envelope, final @Nullable Object hint) { + final @NotNull SentryEnvelope envelope, final @Nullable Map hint) { Objects.requireNonNull(envelope, "SentryEnvelope is required."); try { @@ -401,7 +407,7 @@ public void captureSession(final @NotNull Session session, final @Nullable Objec @NotNull SentryTransaction transaction, @Nullable TraceState traceState, final @Nullable Scope scope, - final @Nullable Object hint) { + final @Nullable Map hint) { Objects.requireNonNull(transaction, "Transaction is required."); options @@ -468,7 +474,9 @@ public void captureSession(final @NotNull Session session, final @Nullable Objec } private @Nullable SentryEvent applyScope( - @NotNull SentryEvent event, final @Nullable Scope scope, final @Nullable Object hint) { + @NotNull SentryEvent event, + final @Nullable Scope scope, + final @Nullable Map hint) { if (scope != null) { applyScope(event, scope); @@ -546,7 +554,7 @@ private void sortBreadcrumbsByDate( } private @Nullable SentryEvent executeBeforeSend( - @NotNull SentryEvent event, final @Nullable Object hint) { + @NotNull SentryEvent event, final @Nullable Map hint) { final SentryOptions.BeforeSendCallback beforeSend = options.getBeforeSend(); if (beforeSend != null) { try { @@ -566,6 +574,7 @@ private void sortBreadcrumbsByDate( if (e.getMessage() != null) { breadcrumb.setData("sentry:message", e.getMessage()); } + event.addBreadcrumb(breadcrumb); } } diff --git a/sentry/src/main/java/io/sentry/SentryOptions.java b/sentry/src/main/java/io/sentry/SentryOptions.java index 901c47a59e8..f9bd8d9c186 100644 --- a/sentry/src/main/java/io/sentry/SentryOptions.java +++ b/sentry/src/main/java/io/sentry/SentryOptions.java @@ -1453,7 +1453,7 @@ public interface BeforeSendCallback { * @return the original event or the mutated event or null if event was dropped */ @Nullable - SentryEvent execute(@NotNull SentryEvent event, @Nullable Object hint); + SentryEvent execute(@NotNull SentryEvent event, @Nullable Map hint); } /** The BeforeBreadcrumb callback */ @@ -1467,7 +1467,7 @@ public interface BeforeBreadcrumbCallback { * @return the original breadcrumb or the mutated breadcrumb of null if breadcrumb was dropped */ @Nullable - Breadcrumb execute(@NotNull Breadcrumb breadcrumb, @Nullable Object hint); + Breadcrumb execute(@NotNull Breadcrumb breadcrumb, @Nullable Map hint); } /** The traces sampler callback. */ diff --git a/sentry/src/main/java/io/sentry/SentryRuntimeEventProcessor.java b/sentry/src/main/java/io/sentry/SentryRuntimeEventProcessor.java index 184e8e98859..d031f0a61d9 100644 --- a/sentry/src/main/java/io/sentry/SentryRuntimeEventProcessor.java +++ b/sentry/src/main/java/io/sentry/SentryRuntimeEventProcessor.java @@ -2,6 +2,7 @@ import io.sentry.protocol.SentryRuntime; import io.sentry.protocol.SentryTransaction; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -22,13 +23,13 @@ public SentryRuntimeEventProcessor() { @Override public @NotNull SentryEvent process( - final @NotNull SentryEvent event, final @Nullable Object hint) { + final @NotNull SentryEvent event, final @Nullable Map hint) { return process(event); } @Override public @NotNull SentryTransaction process( - final @NotNull SentryTransaction transaction, final @Nullable Object hint) { + final @NotNull SentryTransaction transaction, final @Nullable Map hint) { return process(transaction); } diff --git a/sentry/src/main/java/io/sentry/TypeCheckHint.java b/sentry/src/main/java/io/sentry/TypeCheckHint.java new file mode 100644 index 00000000000..a1631234cc5 --- /dev/null +++ b/sentry/src/main/java/io/sentry/TypeCheckHint.java @@ -0,0 +1,93 @@ +package io.sentry; + +import org.jetbrains.annotations.ApiStatus; + +/** Constants used for Type Check hints. */ +public final class TypeCheckHint { + + @ApiStatus.Internal public static final String SENTRY_TYPE_CHECK_HINT = "sentry:typeCheckHint"; + + /** Used for Synthetic exceptions. */ + public static final String SENTRY_SYNTHETIC_EXCEPTION = "syntheticException"; + + /** Used for Activity breadcrumbs. */ + public static final String ANDROID_ACTIVITY = "android:activity"; + /** Used for Configuration changes breadcrumbs. */ + public static final String ANDROID_CONFIGURATION = "android:configuration"; + /** Used for System breadcrumbs. */ + public static final String ANDROID_INTENT = "android:intent"; + /** Used for Sensor breadcrumbs. */ + public static final String ANDROID_SENSOR_EVENT = "android:sensorEvent"; + /** Used for Gesture breadcrumbs. */ + public static final String ANDROID_MOTION_EVENT = "android:motionEvent"; + /** Used for View breadcrumbs. */ + public static final String ANDROID_VIEW = "android:view"; + /** Used for Fragment breadcrumbs. */ + public static final String ANDROID_FRAGMENT = "android:fragment"; + + /** Used for OkHttp response breadcrumbs. */ + public static final String OKHTTP_RESPONSE = "okHttp:response"; + /** Used for OkHttp Request breadcrumbs. */ + public static final String OKHTTP_REQUEST = "okHttp:request"; + + /** Used for Apollo response breadcrumbs. */ + public static final String APOLLO_RESPONSE = "apollo:response"; + /** Used for Apollo Request breadcrumbs. */ + public static final String APOLLO_REQUEST = "apollo:request"; + + /** Used for GraphQl handler exceptions. */ + public static final String GRAPHQL_HANDLER_PARAMETERS = "graphql:handlerParameters"; + + /** Used for JUL breadcrumbs. */ + public static final String JUL_LOG_RECORD = "jul:logRecord"; + + /** Used for Log4j breadcrumbs. */ + public static final String LOG4J_LOG_EVENT = "log4j:logEvent"; + + /** Used for Logback breadcrumbs. */ + public static final String LOGBACK_LOGGING_EVENT = "logback:loggingEvent"; + + /** Used for OpenFeign response breadcrumbs. */ + public static final String OPEN_FEIGN_RESPONSE = "openFeign:response"; + /** Used for OpenFeign Request breadcrumbs. */ + public static final String OPEN_FEIGN_REQUEST = "openFeign:request"; + + /** Used for Servlet Request breadcrumbs. */ + public static final String SERVLET_REQUEST = "servlet:request"; + + /** Used for Spring resolver exceptions. */ + public static final String SPRING_RESOLVER_RESPONSE = "springResolver:response"; + /** Used for Spring resolver exceptions. */ + public static final String SPRING_RESOLVER_REQUEST = "springResolver:request"; + + /** Used for Spring request filter breadcrumbs. */ + public static final String SPRING_REQUEST_FILTER_RESPONSE = "springRequestFilter:response"; + /** Used for Spring request filter breadcrumbs. */ + public static final String SPRING_REQUEST_FILTER_REQUEST = "springRequestFilter:request"; + + /** Used for Spring request interceptor breadcrumbs. */ + public static final String SPRING_REQUEST_INTERCEPTOR_RESPONSE = + "springRequestInterceptor:response"; + /** Used for Spring request interceptor breadcrumbs. */ + public static final String SPRING_REQUEST_INTERCEPTOR_REQUEST = + "springRequestInterceptor:request"; + /** Used for Spring request interceptor breadcrumbs. */ + public static final String SPRING_REQUEST_INTERCEPTOR_REQUEST_BODY = + "springRequestInterceptor:requestBody"; + + /** Used for Spring WebFlux exception handler. */ + public static final String WEBFLUX_EXCEPTION_HANDLER_RESPONSE = + "webFluxExceptionHandler:response"; + /** Used for Spring WebFlux exception handler. */ + public static final String WEBFLUX_EXCEPTION_HANDLER_REQUEST = "webFluxExceptionHandler:request"; + + /** Used for Spring WebFlux filter breadcrumbs. */ + public static final String WEBFLUX_FILTER_RESPONSE = "webFluxFilter:response"; + /** Used for Spring WebFlux filter breadcrumbs. */ + public static final String WEBFLUX_FILTER_REQUEST = "webFluxFilter:request"; + + /** Used for Spring exchange filter breadcrumbs. */ + public static final String SPRING_EXCHANGE_FILTER_RESPONSE = "springExchangeFilter:response"; + /** Used for Spring exchange filter breadcrumbs. */ + public static final String SPRING_EXCHANGE_FILTER_REQUEST = "springExchangeFilter:request"; +} diff --git a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java index 1f696aa4054..08671dd61ad 100644 --- a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java +++ b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java @@ -1,6 +1,7 @@ package io.sentry; import static io.sentry.SentryLevel.ERROR; +import static io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT; import io.sentry.exception.ExceptionMechanismException; import io.sentry.hints.DiskFlushNotification; @@ -9,6 +10,8 @@ import io.sentry.protocol.Mechanism; import io.sentry.util.Objects; import java.io.Closeable; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import org.jetbrains.annotations.NotNull; @@ -93,7 +96,11 @@ public void uncaughtException(Thread thread, Throwable thrown) { final Throwable throwable = getUnhandledThrowable(thread, thrown); final SentryEvent event = new SentryEvent(throwable); event.setLevel(SentryLevel.FATAL); - hub.captureEvent(event, hint); + + final Map hintMap = new HashMap<>(); + hintMap.put(SENTRY_TYPE_CHECK_HINT, hint); + + hub.captureEvent(event, hintMap); // Block until the event is flushed to disk if (!hint.waitFlush()) { options diff --git a/sentry/src/main/java/io/sentry/cache/EnvelopeCache.java b/sentry/src/main/java/io/sentry/cache/EnvelopeCache.java index 93a970a2b97..ad268702d5a 100644 --- a/sentry/src/main/java/io/sentry/cache/EnvelopeCache.java +++ b/sentry/src/main/java/io/sentry/cache/EnvelopeCache.java @@ -18,6 +18,7 @@ import io.sentry.hints.SessionEnd; import io.sentry.hints.SessionStart; import io.sentry.transport.NoOpEnvelopeCache; +import io.sentry.util.HintUtils; import io.sentry.util.Objects; import java.io.BufferedInputStream; import java.io.BufferedReader; @@ -77,20 +78,22 @@ private EnvelopeCache( } @Override - public void store(final @NotNull SentryEnvelope envelope, final @Nullable Object hint) { + public void store( + final @NotNull SentryEnvelope envelope, final @Nullable Map hint) { Objects.requireNonNull(envelope, "Envelope is required."); rotateCacheIfNeeded(allEnvelopeFiles()); final File currentSessionFile = getCurrentSessionFile(); - if (hint instanceof SessionEnd) { + Object sentrySdkHint = HintUtils.getSentrySdkHint(hint); + if (sentrySdkHint instanceof SessionEnd) { if (!currentSessionFile.delete()) { options.getLogger().log(WARNING, "Current envelope doesn't exist."); } } - if (hint instanceof SessionStart) { + if (sentrySdkHint instanceof SessionStart) { boolean crashedLastRun = false; // TODO: should we move this to AppLifecycleIntegration? and do on SDK init? but it's too much @@ -198,7 +201,7 @@ public void store(final @NotNull SentryEnvelope envelope, final @Nullable Object writeEnvelopeToDisk(envelopeFile, envelope); // write file to the disk when its about to crash so crashedLastRun can be marked on restart - if (hint instanceof DiskFlushNotification) { + if (sentrySdkHint instanceof DiskFlushNotification) { writeCrashMarkerFile(); } } diff --git a/sentry/src/main/java/io/sentry/cache/IEnvelopeCache.java b/sentry/src/main/java/io/sentry/cache/IEnvelopeCache.java index eca86ca01a8..0ada72ea86b 100644 --- a/sentry/src/main/java/io/sentry/cache/IEnvelopeCache.java +++ b/sentry/src/main/java/io/sentry/cache/IEnvelopeCache.java @@ -1,12 +1,13 @@ package io.sentry.cache; import io.sentry.SentryEnvelope; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface IEnvelopeCache extends Iterable { - void store(@NotNull SentryEnvelope envelope, @Nullable Object hint); + void store(@NotNull SentryEnvelope envelope, @Nullable Map hint); default void store(@NotNull SentryEnvelope envelope) { store(envelope, null); diff --git a/sentry/src/main/java/io/sentry/transport/AsyncHttpTransport.java b/sentry/src/main/java/io/sentry/transport/AsyncHttpTransport.java index ee2c2aebb20..c8e9ce57f3d 100644 --- a/sentry/src/main/java/io/sentry/transport/AsyncHttpTransport.java +++ b/sentry/src/main/java/io/sentry/transport/AsyncHttpTransport.java @@ -10,9 +10,11 @@ import io.sentry.hints.DiskFlushNotification; import io.sentry.hints.Retryable; import io.sentry.hints.SubmissionResult; +import io.sentry.util.HintUtils; import io.sentry.util.LogUtils; import io.sentry.util.Objects; import java.io.IOException; +import java.util.Map; import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; @@ -63,18 +65,19 @@ public AsyncHttpTransport( @Override @SuppressWarnings("FutureReturnValueIgnored") - public void send(final @NotNull SentryEnvelope envelope, final @Nullable Object hint) + public void send(final @NotNull SentryEnvelope envelope, final @Nullable Map hint) throws IOException { // For now no caching on envelopes IEnvelopeCache currentEnvelopeCache = envelopeCache; boolean cached = false; - if (hint instanceof Cached) { + Object sentrySdkHint = HintUtils.getSentrySdkHint(hint); + if (sentrySdkHint instanceof Cached) { currentEnvelopeCache = NoOpEnvelopeCache.getInstance(); cached = true; options.getLogger().log(SentryLevel.DEBUG, "Captured Envelope is already cached"); } - final SentryEnvelope filteredEnvelope = rateLimiter.filter(envelope, hint); + final SentryEnvelope filteredEnvelope = rateLimiter.filter(envelope, sentrySdkHint); if (filteredEnvelope == null) { if (cached) { @@ -100,11 +103,12 @@ private static QueuedThreadPoolExecutor initExecutor( if (r instanceof EnvelopeSender) { final EnvelopeSender envelopeSender = (EnvelopeSender) r; - if (!(envelopeSender.hint instanceof Cached)) { + Object sentrySdkHint = HintUtils.getSentrySdkHint(envelopeSender.hint); + if (!(sentrySdkHint instanceof Cached)) { envelopeCache.store(envelopeSender.envelope, envelopeSender.hint); } - markHintWhenSendingFailed(envelopeSender.hint, true); + markHintWhenSendingFailed(sentrySdkHint, true); logger.log(SentryLevel.WARNING, "Envelope rejected"); } }; @@ -138,15 +142,16 @@ public void close() throws IOException { /** * It marks the hints when sending has failed, so it's not necessary to wait the timeout * - * @param hint the Hint + * @param sentrySdkHint the Hint * @param retry if event should be retried or not */ - private static void markHintWhenSendingFailed(final @Nullable Object hint, final boolean retry) { - if (hint instanceof SubmissionResult) { - ((SubmissionResult) hint).setResult(false); + private static void markHintWhenSendingFailed( + final @Nullable Object sentrySdkHint, final boolean retry) { + if (sentrySdkHint instanceof SubmissionResult) { + ((SubmissionResult) sentrySdkHint).setResult(false); } - if (hint instanceof Retryable) { - ((Retryable) hint).setRetry(retry); + if (sentrySdkHint instanceof Retryable) { + ((Retryable) sentrySdkHint).setRetry(retry); } } @@ -163,13 +168,13 @@ private static final class AsyncConnectionThreadFactory implements ThreadFactory private final class EnvelopeSender implements Runnable { private final @NotNull SentryEnvelope envelope; - private final @Nullable Object hint; + private final @Nullable Map hint; private final @NotNull IEnvelopeCache envelopeCache; private final TransportResult failedResult = TransportResult.error(); EnvelopeSender( final @NotNull SentryEnvelope envelope, - final @Nullable Object hint, + final @Nullable Map hint, final @NotNull IEnvelopeCache envelopeCache) { this.envelope = Objects.requireNonNull(envelope, "Envelope is required."); this.hint = hint; @@ -186,11 +191,12 @@ public void run() { options.getLogger().log(SentryLevel.ERROR, e, "Envelope submission failed"); throw e; } finally { - if (hint instanceof SubmissionResult) { + Object sentrySdkHint = HintUtils.getSentrySdkHint(hint); + if (sentrySdkHint instanceof SubmissionResult) { options .getLogger() .log(SentryLevel.DEBUG, "Marking envelope submission result: %s", result.isSuccess()); - ((SubmissionResult) hint).setResult(result.isSuccess()); + ((SubmissionResult) sentrySdkHint).setResult(result.isSuccess()); } } } @@ -200,8 +206,9 @@ public void run() { envelopeCache.store(envelope, hint); - if (hint instanceof DiskFlushNotification) { - ((DiskFlushNotification) hint).markFlushed(); + Object sentrySdkHint = HintUtils.getSentrySdkHint(hint); + if (sentrySdkHint instanceof DiskFlushNotification) { + ((DiskFlushNotification) sentrySdkHint).markFlushed(); options.getLogger().log(SentryLevel.DEBUG, "Disk flush envelope fired"); } @@ -221,19 +228,19 @@ public void run() { } } catch (IOException e) { // Failure due to IO is allowed to retry the event - if (hint instanceof Retryable) { - ((Retryable) hint).setRetry(true); + if (sentrySdkHint instanceof Retryable) { + ((Retryable) sentrySdkHint).setRetry(true); } else { - LogUtils.logIfNotRetryable(options.getLogger(), hint); + LogUtils.logIfNotRetryable(options.getLogger(), sentrySdkHint); } throw new IllegalStateException("Sending the event failed.", e); } } else { // If transportGate is blocking from sending, allowed to retry - if (hint instanceof Retryable) { - ((Retryable) hint).setRetry(true); + if (sentrySdkHint instanceof Retryable) { + ((Retryable) sentrySdkHint).setRetry(true); } else { - LogUtils.logIfNotRetryable(options.getLogger(), hint); + LogUtils.logIfNotRetryable(options.getLogger(), sentrySdkHint); } } return result; diff --git a/sentry/src/main/java/io/sentry/transport/ITransport.java b/sentry/src/main/java/io/sentry/transport/ITransport.java index 1a677fe233e..b528e575f3d 100644 --- a/sentry/src/main/java/io/sentry/transport/ITransport.java +++ b/sentry/src/main/java/io/sentry/transport/ITransport.java @@ -3,12 +3,14 @@ import io.sentry.SentryEnvelope; import java.io.Closeable; import java.io.IOException; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** A transport is in charge of sending the event to the Sentry server. */ public interface ITransport extends Closeable { - void send(@NotNull SentryEnvelope envelope, @Nullable Object hint) throws IOException; + void send(@NotNull SentryEnvelope envelope, @Nullable Map hint) + throws IOException; default void send(@NotNull SentryEnvelope envelope) throws IOException { send(envelope, null); diff --git a/sentry/src/main/java/io/sentry/transport/NoOpEnvelopeCache.java b/sentry/src/main/java/io/sentry/transport/NoOpEnvelopeCache.java index d48b083a0c5..736cccb4af6 100644 --- a/sentry/src/main/java/io/sentry/transport/NoOpEnvelopeCache.java +++ b/sentry/src/main/java/io/sentry/transport/NoOpEnvelopeCache.java @@ -4,6 +4,7 @@ import io.sentry.cache.IEnvelopeCache; import java.util.ArrayList; import java.util.Iterator; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,7 +16,7 @@ public static NoOpEnvelopeCache getInstance() { } @Override - public void store(@NotNull SentryEnvelope envelope, @Nullable Object hint) {} + public void store(@NotNull SentryEnvelope envelope, @Nullable Map hint) {} @Override public void discard(@NotNull SentryEnvelope envelope) {} diff --git a/sentry/src/main/java/io/sentry/transport/NoOpTransport.java b/sentry/src/main/java/io/sentry/transport/NoOpTransport.java index c5721d99f72..435e0edd50a 100644 --- a/sentry/src/main/java/io/sentry/transport/NoOpTransport.java +++ b/sentry/src/main/java/io/sentry/transport/NoOpTransport.java @@ -2,6 +2,7 @@ import io.sentry.SentryEnvelope; import java.io.IOException; +import java.util.Map; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -18,7 +19,7 @@ public final class NoOpTransport implements ITransport { private NoOpTransport() {} @Override - public void send(final @NotNull SentryEnvelope envelope, final @Nullable Object hint) + public void send(final @NotNull SentryEnvelope envelope, final @Nullable Map hint) throws IOException {} @Override diff --git a/sentry/src/main/java/io/sentry/transport/RateLimiter.java b/sentry/src/main/java/io/sentry/transport/RateLimiter.java index 0ab3af7fa1e..699b1189d5d 100644 --- a/sentry/src/main/java/io/sentry/transport/RateLimiter.java +++ b/sentry/src/main/java/io/sentry/transport/RateLimiter.java @@ -60,7 +60,7 @@ public RateLimiter(@NotNull ILogger logger) { } public @Nullable SentryEnvelope filter( - final @NotNull SentryEnvelope envelope, final @Nullable Object hint) { + final @NotNull SentryEnvelope envelope, final @Nullable Object sentrySdkHint) { // Optimize for/No allocations if no items are under 429 List dropItems = null; for (SentryEnvelopeItem item : envelope.getItems()) { @@ -88,7 +88,7 @@ public RateLimiter(@NotNull ILogger logger) { if (toSend.isEmpty()) { logger.log(SentryLevel.INFO, "Envelope discarded due all items rate limited."); - markHintWhenSendingFailed(hint, false); + markHintWhenSendingFailed(sentrySdkHint, false); return null; } @@ -100,15 +100,16 @@ public RateLimiter(@NotNull ILogger logger) { /** * It marks the hints when sending has failed, so it's not necessary to wait the timeout * - * @param hint the Hint + * @param sentrySdkHint the Hint * @param retry if event should be retried or not */ - private static void markHintWhenSendingFailed(final @Nullable Object hint, final boolean retry) { - if (hint instanceof SubmissionResult) { - ((SubmissionResult) hint).setResult(false); + private static void markHintWhenSendingFailed( + final @Nullable Object sentrySdkHint, final boolean retry) { + if (sentrySdkHint instanceof SubmissionResult) { + ((SubmissionResult) sentrySdkHint).setResult(false); } - if (hint instanceof Retryable) { - ((Retryable) hint).setRetry(retry); + if (sentrySdkHint instanceof Retryable) { + ((Retryable) sentrySdkHint).setRetry(retry); } } diff --git a/sentry/src/main/java/io/sentry/transport/StdoutTransport.java b/sentry/src/main/java/io/sentry/transport/StdoutTransport.java index c30f1df411b..2f3783f72b4 100644 --- a/sentry/src/main/java/io/sentry/transport/StdoutTransport.java +++ b/sentry/src/main/java/io/sentry/transport/StdoutTransport.java @@ -4,6 +4,7 @@ import io.sentry.SentryEnvelope; import io.sentry.util.Objects; import java.io.IOException; +import java.util.Map; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,7 +17,7 @@ public StdoutTransport(final @NotNull ISerializer serializer) { } @Override - public void send(final @NotNull SentryEnvelope envelope, final @Nullable Object hint) + public void send(final @NotNull SentryEnvelope envelope, final @Nullable Map hint) throws IOException { Objects.requireNonNull(envelope, "SentryEnvelope is required"); diff --git a/sentry/src/main/java/io/sentry/util/ApplyScopeUtils.java b/sentry/src/main/java/io/sentry/util/ApplyScopeUtils.java deleted file mode 100644 index 420540ae051..00000000000 --- a/sentry/src/main/java/io/sentry/util/ApplyScopeUtils.java +++ /dev/null @@ -1,24 +0,0 @@ -package io.sentry.util; - -import io.sentry.hints.ApplyScopeData; -import io.sentry.hints.Cached; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; - -/** Util class for Applying or not scope's data to an event */ -@ApiStatus.Internal -public final class ApplyScopeUtils { - - private ApplyScopeUtils() {} - - /** - * Scope's data should be applied if: Hint is of the type ApplyScopeData or Hint is not Cached - * (this includes a null hint) - * - * @param hint the hint - * @return true if it should apply scope's data or false otherwise - */ - public static boolean shouldApplyScopeData(final @Nullable Object hint) { - return (!(hint instanceof Cached) || (hint instanceof ApplyScopeData)); - } -} diff --git a/sentry/src/main/java/io/sentry/util/HintUtils.java b/sentry/src/main/java/io/sentry/util/HintUtils.java new file mode 100644 index 00000000000..ce6c36632cb --- /dev/null +++ b/sentry/src/main/java/io/sentry/util/HintUtils.java @@ -0,0 +1,35 @@ +package io.sentry.util; + +import static io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT; + +import io.sentry.hints.ApplyScopeData; +import io.sentry.hints.Cached; +import java.util.Map; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +/** Util class for Applying or not scope's data to an event */ +@ApiStatus.Internal +public final class HintUtils { + + private HintUtils() {} + + /** + * Scope's data should be applied if: Hint is of the type ApplyScopeData or Hint is not Cached + * (this includes a null hint) + * + * @param hint the hint + * @return true if it should apply scope's data or false otherwise + */ + public static boolean shouldApplyScopeData(final @Nullable Map hint) { + Object SentrySdkHint = getSentrySdkHint(hint); + return (!(SentrySdkHint instanceof Cached) || (SentrySdkHint instanceof ApplyScopeData)); + } + + public static @Nullable Object getSentrySdkHint(final @Nullable Map hint) { + if (hint == null) { + return null; + } + return hint.get(SENTRY_TYPE_CHECK_HINT); + } +} diff --git a/sentry/src/main/java/io/sentry/util/LogUtils.java b/sentry/src/main/java/io/sentry/util/LogUtils.java index 6e5ba9a619b..c594ec1d120 100644 --- a/sentry/src/main/java/io/sentry/util/LogUtils.java +++ b/sentry/src/main/java/io/sentry/util/LogUtils.java @@ -9,17 +9,19 @@ @ApiStatus.Internal public final class LogUtils { - public static void logIfNotFlushable(final @NotNull ILogger logger, final @Nullable Object hint) { + public static void logIfNotFlushable( + final @NotNull ILogger logger, final @Nullable Object sentrySdkHint) { logger.log( SentryLevel.DEBUG, "%s is not Flushable", - hint != null ? hint.getClass().getCanonicalName() : "Hint"); + sentrySdkHint != null ? sentrySdkHint.getClass().getCanonicalName() : "Hint"); } - public static void logIfNotRetryable(final @NotNull ILogger logger, final @Nullable Object hint) { + public static void logIfNotRetryable( + final @NotNull ILogger logger, final @Nullable Object sentrySdkHint) { logger.log( SentryLevel.DEBUG, "%s is not Retryable", - hint != null ? hint.getClass().getCanonicalName() : "Hint"); + sentrySdkHint != null ? sentrySdkHint.getClass().getCanonicalName() : "Hint"); } } diff --git a/sentry/src/test/java/io/sentry/CustomCachedApplyScopeDataHint.kt b/sentry/src/test/java/io/sentry/CustomCachedApplyScopeDataHint.kt new file mode 100644 index 00000000000..639d7bcd8c0 --- /dev/null +++ b/sentry/src/test/java/io/sentry/CustomCachedApplyScopeDataHint.kt @@ -0,0 +1,6 @@ +package io.sentry + +import io.sentry.hints.ApplyScopeData +import io.sentry.hints.Cached + +class CustomCachedApplyScopeDataHint : Cached, ApplyScopeData diff --git a/sentry/src/test/java/io/sentry/CustomEventProcessor.kt b/sentry/src/test/java/io/sentry/CustomEventProcessor.kt index 5845c628680..a519c9983f0 100644 --- a/sentry/src/test/java/io/sentry/CustomEventProcessor.kt +++ b/sentry/src/test/java/io/sentry/CustomEventProcessor.kt @@ -1,5 +1,5 @@ package io.sentry class CustomEventProcessor : EventProcessor { - override fun process(event: SentryEvent, hint: Any?): SentryEvent? = null + override fun process(event: SentryEvent, hint: Map?): SentryEvent? = null } diff --git a/sentry/src/test/java/io/sentry/EnvelopeSenderTest.kt b/sentry/src/test/java/io/sentry/EnvelopeSenderTest.kt index d0482bd7209..f9451945a74 100644 --- a/sentry/src/test/java/io/sentry/EnvelopeSenderTest.kt +++ b/sentry/src/test/java/io/sentry/EnvelopeSenderTest.kt @@ -7,6 +7,7 @@ import com.nhaarman.mockitokotlin2.mock import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions import com.nhaarman.mockitokotlin2.whenever +import io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT import io.sentry.cache.EnvelopeCache import io.sentry.hints.Retryable import io.sentry.util.noFlushTimeout @@ -95,7 +96,9 @@ class EnvelopeSenderTest { val sut = fixture.getSut() val testFile = File(Files.createTempFile(tempDirectory, "send-cached-event-test", EnvelopeCache.SUFFIX_ENVELOPE_FILE).toUri()) testFile.deleteOnExit() - sut.processFile(testFile, mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + sut.processFile(testFile, hintsMap) verify(fixture.logger)!!.log(eq(SentryLevel.ERROR), eq(expected), eq("Failed to capture cached envelope %s"), eq(testFile.absolutePath)) verifyNoMoreInteractions(fixture.hub) assertFalse(testFile.exists()) diff --git a/sentry/src/test/java/io/sentry/HubTest.kt b/sentry/src/test/java/io/sentry/HubTest.kt index b36722364f4..d8b8e416328 100644 --- a/sentry/src/test/java/io/sentry/HubTest.kt +++ b/sentry/src/test/java/io/sentry/HubTest.kt @@ -14,6 +14,7 @@ import com.nhaarman.mockitokotlin2.times import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions import com.nhaarman.mockitokotlin2.whenever +import io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT import io.sentry.cache.EnvelopeCache import io.sentry.hints.SessionEndHint import io.sentry.hints.SessionStartHint @@ -21,6 +22,7 @@ import io.sentry.protocol.SentryId import io.sentry.protocol.SentryTransaction import io.sentry.protocol.User import io.sentry.test.callMethod +import io.sentry.util.HintUtils import java.io.File import java.nio.file.Files import java.util.Queue @@ -260,7 +262,7 @@ class HubTest { sut.close() sut.captureEvent(SentryEvent()) - verify(mockClient, never()).captureEvent(any(), any()) + verify(mockClient, never()).captureEvent(any(), any>()) } @Test @@ -268,9 +270,9 @@ class HubTest { val (sut, mockClient) = getEnabledHub() val event = SentryEvent() - val hint = { } - sut.captureEvent(event, hint) - verify(mockClient).captureEvent(eq(event), any(), eq(hint)) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to { }) + sut.captureEvent(event, hintsMap) + verify(mockClient).captureEvent(eq(event), any(), eq(hintsMap)) } @Test @@ -278,11 +280,11 @@ class HubTest { val (sut, mockClient) = getEnabledHub() whenever(mockClient.captureEvent(any(), any(), anyOrNull())).thenReturn(SentryId(UUID.randomUUID())) val event = SentryEvent() - val hint = { } - sut.captureEvent(event, hint) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to { }) + sut.captureEvent(event, hintsMap) val lastEventId = sut.lastEventId sut.close() - sut.captureEvent(event, hint) + sut.captureEvent(event, hintsMap) assertEquals(lastEventId, sut.lastEventId) } @@ -291,9 +293,9 @@ class HubTest { val (sut, mockClient) = getEnabledHub() val event = SentryEvent() - val hint = { } - sut.captureEvent(event, hint) - verify(mockClient).captureEvent(eq(event), any(), eq(hint)) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to { }) + sut.captureEvent(event, hintsMap) + verify(mockClient).captureEvent(eq(event), any(), eq(hintsMap)) verify(mockClient, never()).captureSession(any(), any()) } @@ -302,9 +304,9 @@ class HubTest { val (sut, mockClient) = getEnabledHub() val event = SentryEvent() - val hint = { } - sut.captureEvent(event, hint) - verify(mockClient).captureEvent(eq(event), any(), eq(hint)) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to { }) + sut.captureEvent(event, hintsMap) + verify(mockClient).captureEvent(eq(event), any(), eq(hintsMap)) verify(mockClient, never()).captureSession(any(), any()) } @@ -318,10 +320,10 @@ class HubTest { val event = SentryEvent(exception) - val hint = { } - sut.captureEvent(event, hint) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to { }) + sut.captureEvent(event, hintsMap) assertEquals(span.spanContext, event.contexts.trace) - verify(mockClient).captureEvent(eq(event), any(), eq(hint)) + verify(mockClient).captureEvent(eq(event), any(), eq(hintsMap)) } @Test @@ -334,10 +336,10 @@ class HubTest { val event = SentryEvent(RuntimeException(rootCause)) - val hint = { } - sut.captureEvent(event, hint) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to { }) + sut.captureEvent(event, hintsMap) assertEquals(span.spanContext, event.contexts.trace) - verify(mockClient).captureEvent(eq(event), any(), eq(hint)) + verify(mockClient).captureEvent(eq(event), any(), eq(hintsMap)) } @Test @@ -351,10 +353,10 @@ class HubTest { val event = SentryEvent(RuntimeException(exceptionAssignedToSpan)) - val hint = { } - sut.captureEvent(event, hint) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to { }) + sut.captureEvent(event, hintsMap) assertEquals(span.spanContext, event.contexts.trace) - verify(mockClient).captureEvent(eq(event), any(), eq(hint)) + verify(mockClient).captureEvent(eq(event), any(), eq(hintsMap)) } @Test @@ -369,10 +371,10 @@ class HubTest { val originalSpanContext = SpanContext("op") event.contexts.trace = originalSpanContext - val hint = { } - sut.captureEvent(event, hint) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to { }) + sut.captureEvent(event, hintsMap) assertEquals(originalSpanContext, event.contexts.trace) - verify(mockClient).captureEvent(eq(event), any(), eq(hint)) + verify(mockClient).captureEvent(eq(event), any(), eq(hintsMap)) } @Test @@ -381,10 +383,10 @@ class HubTest { val event = SentryEvent(RuntimeException()) - val hint = { } - sut.captureEvent(event, hint) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to { }) + sut.captureEvent(event, hintsMap) assertNull(event.contexts.trace) - verify(mockClient).captureEvent(eq(event), any(), eq(hint)) + verify(mockClient).captureEvent(eq(event), any(), eq(hintsMap)) } //endregion @@ -450,7 +452,8 @@ class HubTest { fun `when captureException is called with a valid argument and hint, captureEvent on the client should be called`() { val (sut, mockClient) = getEnabledHub() - sut.captureException(Throwable(), Object()) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to Object()) + sut.captureException(Throwable(), hintsMap) verify(mockClient).captureEvent(any(), any(), any()) } @@ -967,7 +970,7 @@ class HubTest { sut.bindClient(mockClient) sut.startSession() - verify(mockClient).captureSession(any(), argWhere { it is SessionStartHint }) + verify(mockClient).captureSession(any(), argWhere { HintUtils.getSentrySdkHint(it) is SessionStartHint }) } @Test @@ -983,8 +986,8 @@ class HubTest { sut.startSession() sut.startSession() - verify(mockClient).captureSession(any(), argWhere { it is SessionEndHint }) - verify(mockClient, times(2)).captureSession(any(), argWhere { it is SessionStartHint }) + verify(mockClient).captureSession(any(), argWhere { HintUtils.getSentrySdkHint(it) is SessionEndHint }) + verify(mockClient, times(2)).captureSession(any(), argWhere { HintUtils.getSentrySdkHint(it) is SessionStartHint }) } //endregion @@ -1033,8 +1036,8 @@ class HubTest { sut.startSession() sut.endSession() - verify(mockClient).captureSession(any(), argWhere { it is SessionStartHint }) - verify(mockClient).captureSession(any(), argWhere { it is SessionEndHint }) + verify(mockClient).captureSession(any(), argWhere { HintUtils.getSentrySdkHint(it) is SessionStartHint }) + verify(mockClient).captureSession(any(), argWhere { HintUtils.getSentrySdkHint(it) is SessionEndHint }) } @Test @@ -1067,7 +1070,7 @@ class HubTest { val sentryTracer = SentryTracer(TransactionContext("name", "op"), sut) sentryTracer.finish() - sut.captureTransaction(SentryTransaction(sentryTracer), null) + sut.captureTransaction(SentryTransaction(sentryTracer), null as TraceState?) verify(mockClient, never()).captureTransaction(any(), any(), any()) } @@ -1114,7 +1117,7 @@ class HubTest { sut.bindClient(mockClient) val sentryTracer = SentryTracer(TransactionContext("name", "op", true), sut) - sut.captureTransaction(SentryTransaction(sentryTracer), null) + sut.captureTransaction(SentryTransaction(sentryTracer), null as TraceState?) verify(mockClient, never()).captureTransaction(any(), any(), any(), eq(null)) } diff --git a/sentry/src/test/java/io/sentry/MainEventProcessorTest.kt b/sentry/src/test/java/io/sentry/MainEventProcessorTest.kt index a72936b806d..8ad57d829ea 100644 --- a/sentry/src/test/java/io/sentry/MainEventProcessorTest.kt +++ b/sentry/src/test/java/io/sentry/MainEventProcessorTest.kt @@ -5,8 +5,8 @@ import com.nhaarman.mockitokotlin2.reset import com.nhaarman.mockitokotlin2.times import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.whenever +import io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT import io.sentry.hints.ApplyScopeData -import io.sentry.hints.Cached import io.sentry.protocol.DebugMeta import io.sentry.protocol.SdkVersion import io.sentry.protocol.SentryTransaction @@ -113,7 +113,8 @@ class MainEventProcessorTest { val sut = fixture.getSut() val crashedThread = Thread.currentThread() var event = generateCrashedEvent(crashedThread) - event = sut.process(event, mock()) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + event = sut.process(event, hintsMap) assertEquals("release", event.release) assertEquals("environment", event.environment) @@ -146,7 +147,9 @@ class MainEventProcessorTest { val sut = fixture.getSut() val crashedThread = Thread.currentThread() var event = generateCrashedEvent(crashedThread) - event = sut.process(event, CachedEvent()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CachedEvent()) + event = sut.process(event, hintsMap) assertNull(event.release) assertNull(event.environment) @@ -160,7 +163,9 @@ class MainEventProcessorTest { val sut = fixture.getSut() val crashedThread = Thread.currentThread() var event = generateCrashedEvent(crashedThread) - event = sut.process(event, CustomCachedApplyScopeDataHint()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CustomCachedApplyScopeDataHint()) + event = sut.process(event, hintsMap) assertEquals("release", event.release) assertEquals("environment", event.environment) @@ -403,7 +408,9 @@ class MainEventProcessorTest { val sut = fixture.getSut(attachThreads = false) var event = SentryEvent() - event = sut.process(event, CustomCachedApplyScopeDataHint()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CustomCachedApplyScopeDataHint()) + event = sut.process(event, hintsMap) assertNull(event.threads) } @@ -453,6 +460,4 @@ class MainEventProcessorTest { val actualThrowable = UncaughtExceptionHandlerIntegration.getUnhandledThrowable(crashedThread, mockThrowable) throwable = actualThrowable } - - internal class CustomCachedApplyScopeDataHint : Cached, ApplyScopeData } diff --git a/sentry/src/test/java/io/sentry/OutboxSenderTest.kt b/sentry/src/test/java/io/sentry/OutboxSenderTest.kt index a244c45d73e..3187bdfb9ab 100644 --- a/sentry/src/test/java/io/sentry/OutboxSenderTest.kt +++ b/sentry/src/test/java/io/sentry/OutboxSenderTest.kt @@ -9,6 +9,7 @@ import com.nhaarman.mockitokotlin2.never import com.nhaarman.mockitokotlin2.spy import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.whenever +import io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT import io.sentry.cache.EnvelopeCache import io.sentry.hints.Retryable import io.sentry.protocol.SentryId @@ -60,7 +61,9 @@ class OutboxSenderTest { val sut = fixture.getSut() val path = getTempEnvelope() assertTrue(File(path).exists()) // sanity check - sut.processEnvelopeFile(path, mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + sut.processEnvelopeFile(path, hintsMap) assertFalse(File(path).exists()) // Additionally make sure we have a error logged verify(fixture.logger).log(eq(SentryLevel.ERROR), any(), any()) @@ -74,7 +77,9 @@ class OutboxSenderTest { val sut = fixture.getSut() val path = getTempEnvelope() assertTrue(File(path).exists()) // sanity check - sut.processEnvelopeFile(path, mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + sut.processEnvelopeFile(path, hintsMap) verify(fixture.hub).captureEvent(eq(expected), any()) assertFalse(File(path).exists()) @@ -108,7 +113,9 @@ class OutboxSenderTest { val sut = fixture.getSut() val path = getTempEnvelope(fileName = "envelope-transaction.txt") assertTrue(File(path).exists()) - sut.processEnvelopeFile(path, mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + sut.processEnvelopeFile(path, hintsMap) verify(fixture.hub).captureTransaction( check { @@ -135,7 +142,9 @@ class OutboxSenderTest { val sut = fixture.getSut() val path = getTempEnvelope() assertTrue(File(path).exists()) // sanity check - sut.processEnvelopeFile(path, mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + sut.processEnvelopeFile(path, hintsMap) verify(fixture.hub).captureEvent(any(), any()) assertFalse(File(path).exists()) @@ -151,7 +160,9 @@ class OutboxSenderTest { val sut = fixture.getSut() val path = getTempEnvelope(fileName = "envelope_attachment.txt") assertTrue(File(path).exists()) // sanity check - sut.processEnvelopeFile(path, mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + sut.processEnvelopeFile(path, hintsMap) verify(fixture.hub).captureEnvelope(any(), any()) assertFalse(File(path).exists()) @@ -167,7 +178,9 @@ class OutboxSenderTest { val sut = fixture.getSut() val path = getTempEnvelope() assertTrue(File(path).exists()) // sanity check - sut.processEnvelopeFile(path, mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + sut.processEnvelopeFile(path, hintsMap) // Additionally make sure we have no errors logged verify(fixture.logger).log(eq(SentryLevel.ERROR), any(), any()) @@ -183,7 +196,9 @@ class OutboxSenderTest { val sut = fixture.getSut() val path = getTempEnvelope() assertTrue(File(path).exists()) // sanity check - sut.processEnvelopeFile(path, mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + sut.processEnvelopeFile(path, hintsMap) // Additionally make sure we have no errors logged verify(fixture.logger).log(eq(SentryLevel.ERROR), any(), any()) @@ -194,7 +209,9 @@ class OutboxSenderTest { @Test fun `when processEnvelopeFile is called with a invalid path, logs error`() { val sut = fixture.getSut() - sut.processEnvelopeFile(File.separator + "i-hope-it-doesnt-exist" + File.separator + "file.txt", mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + sut.processEnvelopeFile(File.separator + "i-hope-it-doesnt-exist" + File.separator + "file.txt", hintsMap) verify(fixture.logger).log(eq(SentryLevel.ERROR), any(), argWhere { it is FileNotFoundException }) } diff --git a/sentry/src/test/java/io/sentry/ScopeTest.kt b/sentry/src/test/java/io/sentry/ScopeTest.kt index 95417add637..3b65bb065de 100644 --- a/sentry/src/test/java/io/sentry/ScopeTest.kt +++ b/sentry/src/test/java/io/sentry/ScopeTest.kt @@ -858,7 +858,7 @@ class ScopeTest { private fun eventProcessor(): EventProcessor { return object : EventProcessor { - override fun process(event: SentryEvent, hint: Any?): SentryEvent? { + override fun process(event: SentryEvent, hint: MutableMap?): SentryEvent? { return event } } diff --git a/sentry/src/test/java/io/sentry/SentryClientTest.kt b/sentry/src/test/java/io/sentry/SentryClientTest.kt index 23871e8e29e..08b07908285 100644 --- a/sentry/src/test/java/io/sentry/SentryClientTest.kt +++ b/sentry/src/test/java/io/sentry/SentryClientTest.kt @@ -11,6 +11,7 @@ import com.nhaarman.mockitokotlin2.never import com.nhaarman.mockitokotlin2.verify import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions import com.nhaarman.mockitokotlin2.whenever +import io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT import io.sentry.exception.SentryEnvelopeException import io.sentry.hints.ApplyScopeData import io.sentry.hints.Cached @@ -57,7 +58,7 @@ class SentryClientTest { var sentryOptions: SentryOptions = SentryOptions().apply { dsn = dsnString sdkVersion = SdkVersion("test", "1.2.3") - setDebug(true) + isDebug = true setDiagnosticLevel(SentryLevel.DEBUG) setSerializer(JsonSerializer(this)) setLogger(mock()) @@ -190,9 +191,10 @@ class SentryClientTest { val event = SentryEvent() fixture.sentryOptions.environment = "not to be applied" val sut = fixture.getSut() - val expectedHint = Object() - sut.captureEvent(event, expectedHint) - verify(fixture.transport).send(any(), eq(expectedHint)) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to Object()) + sut.captureEvent(event, hintsMap) + verify(fixture.transport).send(any(), eq(hintsMap)) } @Test @@ -495,7 +497,9 @@ class SentryClientTest { val event = SentryEvent() val scope = Scope(SentryOptions()) scope.level = SentryLevel.FATAL - sut.captureEvent(event, scope, mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + sut.captureEvent(event, scope, hintsMap) assertNotEquals(scope.level, event.level) } @@ -507,7 +511,9 @@ class SentryClientTest { val event = SentryEvent() val scope = Scope(SentryOptions()) scope.level = SentryLevel.FATAL - sut.captureEvent(event, scope, Object()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to Object()) + sut.captureEvent(event, scope, hintsMap) assertEquals(scope.level, event.level) } @@ -519,7 +525,9 @@ class SentryClientTest { val event = SentryEvent() val scope = Scope(SentryOptions()) scope.level = SentryLevel.FATAL - sut.captureEvent(event, scope, mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + sut.captureEvent(event, scope, hintsMap) assertEquals(scope.level, event.level) } @@ -531,7 +539,9 @@ class SentryClientTest { val event = SentryEvent() val scope = Scope(SentryOptions()) scope.level = SentryLevel.FATAL - sut.captureEvent(event, scope, mock()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CustomCachedApplyScopeDataHint()) + sut.captureEvent(event, scope, hintsMap) assertEquals(scope.level, event.level) } @@ -1277,15 +1287,13 @@ class SentryClientTest { ) } - internal class CustomCachedApplyScopeDataHint : Cached, ApplyScopeData - internal class DiskFlushNotificationHint : DiskFlushNotification { override fun markFlushed() {} } private fun eventProcessorThrows(): EventProcessor { return object : EventProcessor { - override fun process(event: SentryEvent, hint: Any?): SentryEvent? { + override fun process(event: SentryEvent, hint: Map?): SentryEvent? { throw Throwable() } } diff --git a/sentry/src/test/java/io/sentry/SentryTracerTest.kt b/sentry/src/test/java/io/sentry/SentryTracerTest.kt index 29da535ee2c..0ab1a6f8a0c 100644 --- a/sentry/src/test/java/io/sentry/SentryTracerTest.kt +++ b/sentry/src/test/java/io/sentry/SentryTracerTest.kt @@ -118,7 +118,7 @@ class SentryTracerTest { check { assertEquals(it.transaction, tracer.name) }, - anyOrNull() + anyOrNull() ) } @@ -153,7 +153,7 @@ class SentryTracerTest { assertEquals(emptyMap(), it.tags) } }, - anyOrNull() + anyOrNull() ) } @@ -169,7 +169,7 @@ class SentryTracerTest { assertEquals(1, it.spans.size) assertEquals("op1", it.spans.first().op) }, - anyOrNull() + anyOrNull() ) } @@ -300,7 +300,7 @@ class SentryTracerTest { assertEquals(SpanStatus.OK, it.status) } }, - anyOrNull() + anyOrNull() ) assertEquals(SpanStatus.OK, transaction.status) @@ -342,7 +342,7 @@ class SentryTracerTest { val transaction = fixture.getSut(waitForChildren = true) transaction.startChild("op") transaction.finish() - verify(fixture.hub, never()).captureTransaction(any(), any()) + verify(fixture.hub, never()).captureTransaction(any(), any()) } @Test @@ -351,7 +351,7 @@ class SentryTracerTest { val child = transaction.startChild("op") child.finish() transaction.finish() - verify(fixture.hub).captureTransaction(any(), anyOrNull()) + verify(fixture.hub).captureTransaction(any(), anyOrNull()) } @Test @@ -372,7 +372,7 @@ class SentryTracerTest { val transaction = fixture.getSut(waitForChildren = true) val child = transaction.startChild("op") child.finish() - verify(fixture.hub, never()).captureTransaction(any(), any()) + verify(fixture.hub, never()).captureTransaction(any(), any()) } @Test @@ -380,13 +380,13 @@ class SentryTracerTest { val transaction = fixture.getSut(waitForChildren = true) val child = transaction.startChild("op") transaction.finish(SpanStatus.INVALID_ARGUMENT) - verify(fixture.hub, never()).captureTransaction(any(), any()) + verify(fixture.hub, never()).captureTransaction(any(), any()) child.finish() verify(fixture.hub, times(1)).captureTransaction( check { assertEquals(SpanStatus.INVALID_ARGUMENT, it.status) }, - anyOrNull() + anyOrNull() ) } @@ -404,7 +404,7 @@ class SentryTracerTest { assertEquals(SpanStatus.DEADLINE_EXCEEDED, it.spans[0].status) assertEquals(SpanStatus.DEADLINE_EXCEEDED, it.spans[1].status) }, - anyOrNull() + anyOrNull() ) } @@ -472,7 +472,7 @@ class SentryTracerTest { check { assertEquals("val", it.getExtra("key")) }, - anyOrNull() + anyOrNull() ) } @@ -489,7 +489,7 @@ class SentryTracerTest { assertEquals("val", it["key"]) } }, - anyOrNull() + anyOrNull() ) } } diff --git a/sentry/src/test/java/io/sentry/cache/EnvelopeCacheTest.kt b/sentry/src/test/java/io/sentry/cache/EnvelopeCacheTest.kt index 2352fad0552..76400ef545d 100644 --- a/sentry/src/test/java/io/sentry/cache/EnvelopeCacheTest.kt +++ b/sentry/src/test/java/io/sentry/cache/EnvelopeCacheTest.kt @@ -13,6 +13,7 @@ import io.sentry.SentryEvent import io.sentry.SentryLevel import io.sentry.SentryOptions import io.sentry.Session +import io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT import io.sentry.cache.EnvelopeCache.PREFIX_CURRENT_SESSION_FILE import io.sentry.cache.EnvelopeCache.SUFFIX_CURRENT_SESSION_FILE import io.sentry.hints.DiskFlushNotification @@ -90,7 +91,9 @@ class EnvelopeCacheTest { val file = File(fixture.options.cacheDirPath!!) val envelope = SentryEnvelope.from(fixture.serializer, createSession(), null) - cache.store(envelope, SessionStartHint()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to SessionStartHint()) + cache.store(envelope, hintsMap) val currentFile = File(fixture.options.cacheDirPath!!, "$PREFIX_CURRENT_SESSION_FILE$SUFFIX_CURRENT_SESSION_FILE") assertTrue(currentFile.exists()) @@ -105,12 +108,15 @@ class EnvelopeCacheTest { val file = File(fixture.options.cacheDirPath!!) val envelope = SentryEnvelope.from(fixture.serializer, createSession(), null) - cache.store(envelope, SessionStartHint()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to SessionStartHint()) + cache.store(envelope, hintsMap) val currentFile = File(fixture.options.cacheDirPath!!, "$PREFIX_CURRENT_SESSION_FILE$SUFFIX_CURRENT_SESSION_FILE") assertTrue(currentFile.exists()) - cache.store(envelope, SessionEndHint()) + hintsMap[SENTRY_TYPE_CHECK_HINT] = SessionEndHint() + cache.store(envelope, hintsMap) assertFalse(currentFile.exists()) file.deleteRecursively() @@ -123,7 +129,9 @@ class EnvelopeCacheTest { val file = File(fixture.options.cacheDirPath!!) val envelope = SentryEnvelope.from(fixture.serializer, createSession(), null) - cache.store(envelope, SessionStartHint()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to SessionStartHint()) + cache.store(envelope, hintsMap) val currentFile = File(fixture.options.cacheDirPath!!, "$PREFIX_CURRENT_SESSION_FILE$SUFFIX_CURRENT_SESSION_FILE") assertTrue(currentFile.exists()) @@ -141,11 +149,13 @@ class EnvelopeCacheTest { val cache = fixture.getSUT() val envelope = SentryEnvelope.from(fixture.serializer, createSession(), null) - cache.store(envelope, SessionStartHint()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to SessionStartHint()) + cache.store(envelope, hintsMap) val newEnvelope = SentryEnvelope.from(fixture.serializer, createSession(), null) - cache.store(newEnvelope, SessionStartHint()) + cache.store(newEnvelope, hintsMap) verify(fixture.logger).log(eq(SentryLevel.WARNING), eq("Current session is not ended, we'd need to end it.")) } @@ -159,11 +169,13 @@ class EnvelopeCacheTest { assertTrue(markerFile.exists()) val envelope = SentryEnvelope.from(fixture.serializer, createSession(), null) - cache.store(envelope, SessionStartHint()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to SessionStartHint()) + cache.store(envelope, hintsMap) val newEnvelope = SentryEnvelope.from(fixture.serializer, createSession(), null) - cache.store(newEnvelope, SessionStartHint()) + cache.store(newEnvelope, hintsMap) verify(fixture.logger).log(eq(SentryLevel.INFO), eq("Crash marker file exists, last Session is gonna be Crashed.")) assertFalse(markerFile.exists()) file.deleteRecursively() @@ -179,11 +191,13 @@ class EnvelopeCacheTest { val date = "2020-02-07T14:16:00.000Z" markerFile.writeText(charset = Charsets.UTF_8, text = date) val envelope = SentryEnvelope.from(fixture.serializer, createSession(), null) - cache.store(envelope, SessionStartHint()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to SessionStartHint()) + cache.store(envelope, hintsMap) val newEnvelope = SentryEnvelope.from(fixture.serializer, createSession(), null) - cache.store(newEnvelope, SessionStartHint()) + cache.store(newEnvelope, hintsMap) assertFalse(markerFile.exists()) file.deleteRecursively() File(fixture.options.cacheDirPath!!).deleteRecursively() @@ -199,14 +213,16 @@ class EnvelopeCacheTest { assertTrue(markerFile.exists()) val envelope = SentryEnvelope.from(fixture.serializer, createSession(), null) - cache.store(envelope, SessionStartHint()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to SessionStartHint()) + cache.store(envelope, hintsMap) val newEnvelope = SentryEnvelope.from(fixture.serializer, createSession(), null) // since the first store call would set as readCrashedLastRun=true SentryCrashLastRunState.getInstance().reset() - cache.store(newEnvelope, SessionStartHint()) + cache.store(newEnvelope, hintsMap) verify(fixture.logger).log(eq(SentryLevel.INFO), eq("Crash marker file exists, last Session is gonna be Crashed.")) assertFalse(markerFile.exists()) file.deleteRecursively() @@ -224,7 +240,9 @@ class EnvelopeCacheTest { assertTrue(markerFile.exists()) val envelope = SentryEnvelope.from(fixture.serializer, createSession(), null) - cache.store(envelope, SessionStartHint()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to SessionStartHint()) + cache.store(envelope, hintsMap) // passing empty string since readCrashedLastRun is already set assertTrue(SentryCrashLastRunState.getInstance().isCrashedLastRun("", false)!!) @@ -239,7 +257,9 @@ class EnvelopeCacheTest { assertFalse(markerFile.exists()) val envelope = SentryEnvelope.from(fixture.serializer, SentryEvent(), null) - cache.store(envelope, DiskFlushHint()) + + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to DiskFlushHint()) + cache.store(envelope, hintsMap) assertTrue(markerFile.exists()) } diff --git a/sentry/src/test/java/io/sentry/transport/AsyncHttpTransportTest.kt b/sentry/src/test/java/io/sentry/transport/AsyncHttpTransportTest.kt index c0bc06b4f48..f2881965c7a 100644 --- a/sentry/src/test/java/io/sentry/transport/AsyncHttpTransportTest.kt +++ b/sentry/src/test/java/io/sentry/transport/AsyncHttpTransportTest.kt @@ -16,6 +16,7 @@ import io.sentry.SentryEnvelopeItem import io.sentry.SentryEvent import io.sentry.SentryOptions import io.sentry.Session +import io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT import io.sentry.dsnString import io.sentry.protocol.User import java.io.IOException @@ -179,7 +180,8 @@ class AsyncHttpTransportTest { whenever(fixture.rateLimiter.filter(any(), anyOrNull())).thenReturn(null) // when - fixture.getSUT().send(envelope, CachedEvent()) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CachedEvent()) + fixture.getSUT().send(envelope, hintsMap) // then verify(fixture.sentryOptions.envelopeDiskCache).discard(any()) @@ -236,7 +238,8 @@ class AsyncHttpTransportTest { val envelope = SentryEnvelope.from(fixture.sentryOptions.serializer, ev, null) // when - fixture.getSUT().send(envelope, CachedEvent()) + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CachedEvent()) + fixture.getSUT().send(envelope, hintsMap) // then verify(fixture.sentryOptions.envelopeDiskCache).discard(any()) diff --git a/sentry/src/test/java/io/sentry/util/ApplyScopeUtilsTest.kt b/sentry/src/test/java/io/sentry/util/ApplyScopeUtilsTest.kt deleted file mode 100644 index 7b7a774d817..00000000000 --- a/sentry/src/test/java/io/sentry/util/ApplyScopeUtilsTest.kt +++ /dev/null @@ -1,31 +0,0 @@ -package io.sentry.util - -import com.nhaarman.mockitokotlin2.mock -import io.sentry.hints.ApplyScopeData -import io.sentry.hints.Cached -import kotlin.test.Test -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class ApplyScopeUtilsTest { - - @Test - fun `if event is Cached, it should not apply scopes data`() { - assertFalse(ApplyScopeUtils.shouldApplyScopeData(mock())) - } - - @Test - fun `if event is not Cached, it should apply scopes data`() { - assertTrue(ApplyScopeUtils.shouldApplyScopeData(null)) - } - - @Test - fun `if event is ApplyScopeData, it should apply scopes data`() { - assertTrue(ApplyScopeUtils.shouldApplyScopeData(mock())) - } - - @Test - fun `if event is Cached but also ApplyScopeData, it should apply scopes data`() { - assertTrue(ApplyScopeUtils.shouldApplyScopeData(mock())) - } -} diff --git a/sentry/src/test/java/io/sentry/util/HintUtilsTest.kt b/sentry/src/test/java/io/sentry/util/HintUtilsTest.kt new file mode 100644 index 00000000000..9e8db6c3002 --- /dev/null +++ b/sentry/src/test/java/io/sentry/util/HintUtilsTest.kt @@ -0,0 +1,36 @@ +package io.sentry.util + +import com.nhaarman.mockitokotlin2.mock +import io.sentry.CustomCachedApplyScopeDataHint +import io.sentry.TypeCheckHint.SENTRY_TYPE_CHECK_HINT +import io.sentry.hints.ApplyScopeData +import io.sentry.hints.Cached +import kotlin.test.Test +import kotlin.test.assertFalse +import kotlin.test.assertTrue + +class HintUtilsTest { + + @Test + fun `if event is Cached, it should not apply scopes data`() { + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + assertFalse(HintUtils.shouldApplyScopeData(hintsMap)) + } + + @Test + fun `if event is not Cached, it should apply scopes data`() { + assertTrue(HintUtils.shouldApplyScopeData(null)) + } + + @Test + fun `if event is ApplyScopeData, it should apply scopes data`() { + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to mock()) + assertTrue(HintUtils.shouldApplyScopeData(hintsMap)) + } + + @Test + fun `if event is Cached but also ApplyScopeData, it should apply scopes data`() { + val hintsMap = mutableMapOf(SENTRY_TYPE_CHECK_HINT to CustomCachedApplyScopeDataHint()) + assertTrue(HintUtils.shouldApplyScopeData(hintsMap)) + } +}