diff --git a/features/dd-sdk-android-rum/api/apiSurface b/features/dd-sdk-android-rum/api/apiSurface index b27a54195f..5cdccce400 100644 --- a/features/dd-sdk-android-rum/api/apiSurface +++ b/features/dd-sdk-android-rum/api/apiSurface @@ -150,6 +150,7 @@ interface com.datadog.android.rum.RumSessionListener class com.datadog.android.rum._RumInternalProxy fun addLongTask(Long, String) fun updatePerformanceMetric(RumPerformanceMetric, Double) + fun setSyntheticsAttribute(String?, String?) companion object fun setTelemetryConfigurationEventMapper(RumConfiguration.Builder, com.datadog.android.event.EventMapper): RumConfiguration.Builder fun setAdditionalConfiguration(RumConfiguration.Builder, Map): RumConfiguration.Builder diff --git a/features/dd-sdk-android-rum/api/dd-sdk-android-rum.api b/features/dd-sdk-android-rum/api/dd-sdk-android-rum.api index 04619cceab..a0c9d3c94e 100644 --- a/features/dd-sdk-android-rum/api/dd-sdk-android-rum.api +++ b/features/dd-sdk-android-rum/api/dd-sdk-android-rum.api @@ -224,6 +224,7 @@ public abstract interface class com/datadog/android/rum/RumSessionListener { public final class com/datadog/android/rum/_RumInternalProxy { public static final field Companion Lcom/datadog/android/rum/_RumInternalProxy$Companion; public final fun addLongTask (JLjava/lang/String;)V + public final fun setSyntheticsAttribute (Ljava/lang/String;Ljava/lang/String;)V public final fun updatePerformanceMetric (Lcom/datadog/android/rum/RumPerformanceMetric;D)V } diff --git a/features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/_RumInternalProxy.kt b/features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/_RumInternalProxy.kt index 23e4ffad47..e78c891047 100644 --- a/features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/_RumInternalProxy.kt +++ b/features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/_RumInternalProxy.kt @@ -6,6 +6,7 @@ package com.datadog.android.rum +import android.content.Intent import com.datadog.android.event.EventMapper import com.datadog.android.lint.InternalApi import com.datadog.android.rum.internal.monitor.AdvancedRumMonitor @@ -31,6 +32,7 @@ import com.datadog.android.telemetry.model.TelemetryConfigurationEvent "VariableNaming" ) class _RumInternalProxy internal constructor(private val rumMonitor: AdvancedRumMonitor) { + @Volatile private var handledSyntheticsAttribute = false fun addLongTask(durationNs: Long, target: String) { rumMonitor.addLongTask(durationNs, target) @@ -40,6 +42,28 @@ class _RumInternalProxy internal constructor(private val rumMonitor: AdvancedRum rumMonitor.updatePerformanceMetric(metric, value) } + @Suppress("MemberVisibilityCanBePrivate") + fun setSyntheticsAttribute(testId: String?, resultId: String?) { + if (this.handledSyntheticsAttribute) { + return + } + + this.handledSyntheticsAttribute = true + if (testId.isNullOrBlank() || resultId.isNullOrBlank()) { + return + } + + rumMonitor.setSyntheticsAttribute(testId, resultId) + } + + internal fun setSyntheticsAttributeFromIntent(intent: Intent) { + @Suppress("TooGenericExceptionCaught") + val extras = try { intent.extras } catch (_: Exception) { null } + val testId = extras?.getString("_dd.synthetics.test_id") + val resultId = extras?.getString("_dd.synthetics.result_id") + this.setSyntheticsAttribute(testId, resultId) + } + companion object { @Suppress("FunctionMaxLength") diff --git a/features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/tracking/ActivityLifecycleTrackingStrategy.kt b/features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/tracking/ActivityLifecycleTrackingStrategy.kt index e0fc555267..79b81a2fe2 100644 --- a/features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/tracking/ActivityLifecycleTrackingStrategy.kt +++ b/features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/tracking/ActivityLifecycleTrackingStrategy.kt @@ -17,7 +17,6 @@ import com.datadog.android.api.SdkCore import com.datadog.android.api.feature.FeatureSdkCore import com.datadog.android.rum.GlobalRumMonitor import com.datadog.android.rum.internal.RumFeature -import com.datadog.android.rum.internal.monitor.AdvancedRumMonitor /** * The ActivityLifecycleTrackingStrategy as an [Application.ActivityLifecycleCallbacks] @@ -92,16 +91,11 @@ abstract class ActivityLifecycleTrackingStrategy : @MainThread override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) { - val intent = activity.intent - val extras = intent.safeExtras - val testId = extras?.getString("_dd.synthetics.test_id") - val resultId = extras?.getString("_dd.synthetics.result_id") - if (!testId.isNullOrBlank() && !resultId.isNullOrBlank()) { - (GlobalRumMonitor.get(sdkCore) as? AdvancedRumMonitor) - ?.setSyntheticsAttribute( - testId, - resultId - ) + if (::sdkCore.isInitialized) { + GlobalRumMonitor + .get(sdkCore) + ._getInternal() + ?.setSyntheticsAttributeFromIntent(activity.intent) } } diff --git a/features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/ActivityLifecycleTrackingStrategyTest.kt b/features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/ActivityLifecycleTrackingStrategyTest.kt index 9167fb3161..1feec68f43 100644 --- a/features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/ActivityLifecycleTrackingStrategyTest.kt +++ b/features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/ActivityLifecycleTrackingStrategyTest.kt @@ -39,6 +39,7 @@ import org.mockito.kotlin.doAnswer import org.mockito.kotlin.doReturn import org.mockito.kotlin.doThrow import org.mockito.kotlin.mock +import org.mockito.kotlin.never import org.mockito.kotlin.verify import org.mockito.kotlin.verifyNoInteractions import org.mockito.kotlin.whenever @@ -166,7 +167,7 @@ internal abstract class ActivityLifecycleTrackingStrategyTest : ObjectTest // verify val mockRumMonitor = rumMonitor.mockInstance as AdvancedRumMonitor - verifyNoInteractions(mockRumMonitor) + verify(mockRumMonitor, never()).setSyntheticsAttribute(any(), any()) } @Test @@ -184,7 +185,7 @@ internal abstract class ActivityLifecycleTrackingStrategyTest : ObjectTest // verify val mockRumMonitor = rumMonitor.mockInstance as AdvancedRumMonitor - verifyNoInteractions(mockRumMonitor) + verify(mockRumMonitor, never()).setSyntheticsAttribute(any(), any()) } companion object { diff --git a/features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/utils/config/GlobalRumMonitorTestConfiguration.kt b/features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/utils/config/GlobalRumMonitorTestConfiguration.kt index 31603c1422..21fe41d39f 100644 --- a/features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/utils/config/GlobalRumMonitorTestConfiguration.kt +++ b/features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/utils/config/GlobalRumMonitorTestConfiguration.kt @@ -9,19 +9,33 @@ package com.datadog.android.rum.utils.config import com.datadog.android.core.InternalSdkCore import com.datadog.android.rum.GlobalRumMonitor import com.datadog.android.rum.RumMonitor +import com.datadog.android.rum._RumInternalProxy import com.datadog.android.rum.internal.monitor.AdvancedRumMonitor import com.datadog.tools.unit.extensions.config.MockTestConfiguration import fr.xgouchet.elmyr.Forge import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever + +@Suppress("TestFunctionName") +internal abstract class InternalAdvancedRumMonitor : AdvancedRumMonitor { + override fun _getInternal(): _RumInternalProxy? { + return null + } +} internal class GlobalRumMonitorTestConfiguration : - MockTestConfiguration(AdvancedRumMonitor::class.java) { + MockTestConfiguration(InternalAdvancedRumMonitor::class.java) { lateinit var mockSdkCore: InternalSdkCore override fun setUp(forge: Forge) { super.setUp(forge) mockSdkCore = mock() + + (mockInstance as? InternalAdvancedRumMonitor)?.let { + whenever(it._getInternal()).thenReturn(_RumInternalProxy(mockInstance as AdvancedRumMonitor)) + } + GlobalRumMonitor.registerIfAbsent(mockInstance, mockSdkCore) }