Skip to content

Commit 7b83fcd

Browse files
committed
RUM-10347: Avoid polling for RumContext in VitalReaderRunnable
1 parent b136c9c commit 7b83fcd

File tree

9 files changed

+163
-92
lines changed

9 files changed

+163
-92
lines changed

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/DatadogCore.kt

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -233,10 +233,8 @@ internal class DatadogCore(
233233
feature.featureContextLock.writeLock().safeTryWithLock(1, TimeUnit.SECONDS) {
234234
val currentContext = feature.featureContext
235235
updateCallback(currentContext)
236-
features.forEach { (key, feature) ->
237-
if (key != featureName) {
238-
feature.notifyContextUpdated(featureName, currentContext)
239-
}
236+
features.values.forEach {
237+
it.notifyContextUpdated(featureName, currentContext)
240238
}
241239
}
242240
}
@@ -312,11 +310,9 @@ internal class DatadogCore(
312310
} else {
313311
feature.setContextUpdateListener(listener)
314312
features.forEach {
315-
if (it.key != featureName) {
316-
val currentContext = getFeatureContext(it.key, false)
317-
if (currentContext.isNotEmpty()) {
318-
listener.onContextUpdate(it.key, currentContext)
319-
}
313+
val currentContext = getFeatureContext(it.key, false)
314+
if (currentContext.isNotEmpty()) {
315+
listener.onContextUpdate(it.key, currentContext)
320316
}
321317
}
322318
}

dd-sdk-android-core/src/test/kotlin/com/datadog/android/core/DatadogCoreTest.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ import org.mockito.kotlin.doAnswer
7272
import org.mockito.kotlin.doReturn
7373
import org.mockito.kotlin.doThrow
7474
import org.mockito.kotlin.mock
75-
import org.mockito.kotlin.never
7675
import org.mockito.kotlin.reset
7776
import org.mockito.kotlin.times
7877
import org.mockito.kotlin.verify
@@ -349,7 +348,7 @@ internal class DatadogCoreTest {
349348
verify(otherFeature).notifyContextUpdated(feature, fakeContext)
350349
verifyNoMoreInteractions(otherFeature)
351350
}
352-
verify(mockFeature, never()).notifyContextUpdated(feature, fakeContext)
351+
verify(mockFeature).notifyContextUpdated(feature, fakeContext)
353352
}
354353

355354
@Test
@@ -745,7 +744,10 @@ internal class DatadogCoreTest {
745744
@StringForgery feature: String
746745
) {
747746
// Given
748-
val mockFeature = mock<SdkFeature>()
747+
val mockFeature = mock<SdkFeature>().apply {
748+
whenever(featureContext) doReturn mutableMapOf()
749+
whenever(featureContextLock) doReturn ReentrantReadWriteLock()
750+
}
749751
val mockContextUpdateListener = mock<FeatureContextUpdateReceiver>()
750752
testedCore.features[feature] = mockFeature
751753

@@ -764,6 +766,7 @@ internal class DatadogCoreTest {
764766
// Given
765767
val mockFeature = mock<SdkFeature>().apply {
766768
whenever(featureContext) doReturn mutableMapOf<String, Any?>()
769+
whenever(featureContextLock) doReturn ReentrantReadWriteLock()
767770
}
768771
val mockContextUpdateListener = mock<FeatureContextUpdateReceiver>()
769772
testedCore.features[feature] = mockFeature
@@ -790,6 +793,7 @@ internal class DatadogCoreTest {
790793
// Given
791794
val mockFeature = mock<SdkFeature>().apply {
792795
whenever(featureContext) doReturn mutableMapOf<String, Any?>()
796+
whenever(featureContextLock) doReturn ReentrantReadWriteLock()
793797
}
794798
val mockContextUpdateListener = mock<FeatureContextUpdateReceiver>()
795799
testedCore.features[feature] = mockFeature
@@ -822,6 +826,7 @@ internal class DatadogCoreTest {
822826
// Given
823827
val mockFeature = mock<SdkFeature>().apply {
824828
whenever(featureContext) doReturn mutableMapOf<String, Any?>()
829+
whenever(featureContextLock) doReturn ReentrantReadWriteLock()
825830
}
826831
val mockContextUpdateListener = mock<FeatureContextUpdateReceiver>()
827832
testedCore.features[feature] = mockFeature

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/RumFeature.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import androidx.annotation.AnyThread
1818
import androidx.annotation.RequiresApi
1919
import com.datadog.android.api.InternalLogger
2020
import com.datadog.android.api.feature.Feature
21+
import com.datadog.android.api.feature.FeatureContextUpdateReceiver
2122
import com.datadog.android.api.feature.FeatureEventReceiver
2223
import com.datadog.android.api.feature.FeatureSdkCore
2324
import com.datadog.android.api.feature.StorageBackedFeature
@@ -144,6 +145,7 @@ internal class RumFeature(
144145
internal var initialResourceIdentifier: InitialResourceIdentifier = NoOpInitialResourceIdentifier()
145146
internal var lastInteractionIdentifier: LastInteractionIdentifier? = NoOpLastInteractionIdentifier()
146147
internal var slowFramesListener: SlowFramesListener? = null
148+
internal val rumContextUpdateReceivers = mutableSetOf<FeatureContextUpdateReceiver>()
147149

148150
private val lateCrashEventHandler by lazy { lateCrashReporterFactory(sdkCore as InternalSdkCore) }
149151

@@ -270,6 +272,11 @@ internal class RumFeature(
270272
override fun onStop() {
271273
sdkCore.removeEventReceiver(name)
272274

275+
rumContextUpdateReceivers.forEach {
276+
sdkCore.removeContextUpdateReceiver(Feature.RUM_FEATURE_NAME, it)
277+
}
278+
rumContextUpdateReceivers.clear()
279+
273280
unregisterTrackingStrategies(appContext)
274281

275282
dataWriter = NoOpDataWriter()
@@ -518,7 +525,10 @@ internal class RumFeature(
518525
vitalObserver,
519526
vitalExecutorService,
520527
periodInMs
521-
)
528+
).apply {
529+
sdkCore.setContextUpdateReceiver(Feature.RUM_FEATURE_NAME, this)
530+
rumContextUpdateReceivers += this
531+
}
522532
vitalExecutorService.scheduleSafe(
523533
"Vitals monitoring",
524534
periodInMs,

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/vitals/VitalReaderRunnable.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package com.datadog.android.rum.internal.vitals
88

99
import com.datadog.android.api.feature.Feature
10+
import com.datadog.android.api.feature.FeatureContextUpdateReceiver
1011
import com.datadog.android.api.feature.FeatureSdkCore
1112
import com.datadog.android.core.internal.utils.scheduleSafe
1213
import com.datadog.android.rum.internal.domain.RumContext
@@ -20,12 +21,13 @@ internal class VitalReaderRunnable(
2021
val observer: VitalObserver,
2122
val executor: ScheduledExecutorService,
2223
private val periodMs: Long
23-
) : Runnable {
24+
) : Runnable, FeatureContextUpdateReceiver {
25+
26+
@Volatile
27+
internal var currentRumContext: RumContext? = null
2428

2529
override fun run() {
26-
val rumContext =
27-
RumContext.fromFeatureContext(sdkCore.getFeatureContext(Feature.RUM_FEATURE_NAME))
28-
val rumViewType = rumContext.viewType
30+
val rumViewType = currentRumContext?.viewType
2931
if (rumViewType == RumViewType.FOREGROUND) {
3032
val data = reader.readVitalData()
3133
if (data != null) {
@@ -40,4 +42,10 @@ internal class VitalReaderRunnable(
4042
this
4143
)
4244
}
45+
46+
override fun onContextUpdate(featureName: String, event: Map<String, Any?>) {
47+
if (featureName == Feature.RUM_FEATURE_NAME) {
48+
currentRumContext = RumContext.fromFeatureContext(event)
49+
}
50+
}
4351
}

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/internal/RumFeatureTest.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import android.app.ApplicationExitInfo
1313
import android.content.Context
1414
import android.os.Build
1515
import com.datadog.android.api.InternalLogger
16+
import com.datadog.android.api.feature.Feature
17+
import com.datadog.android.api.feature.FeatureContextUpdateReceiver
1618
import com.datadog.android.api.storage.NoOpDataWriter
1719
import com.datadog.android.core.InternalSdkCore
1820
import com.datadog.android.core.feature.event.JvmCrash
@@ -649,6 +651,12 @@ internal class RumFeatureTest {
649651
verifyFrameStateAggregatorInitialized(
650652
anyMatchPredicate = { it is FPSVitalListener }
651653
)
654+
argumentCaptor<FeatureContextUpdateReceiver> {
655+
verify(mockSdkCore, times(2))
656+
.setContextUpdateReceiver(eq(Feature.RUM_FEATURE_NAME), capture())
657+
assertThat(testedFeature.rumContextUpdateReceivers).hasSize(allValues.size)
658+
assertThat(testedFeature.rumContextUpdateReceivers).isEqualTo(allValues.toSet())
659+
}
652660
}
653661

654662
@Test
@@ -744,6 +752,21 @@ internal class RumFeatureTest {
744752
verify(mockLongTaskTrackingStrategy).unregister(appContext.mockInstance)
745753
}
746754

755+
fun `M clean up all RUM context update receivers W onStop()`() {
756+
// Given
757+
testedFeature.onInitialize(appContext.mockInstance)
758+
val rumContextUpdateReceivers = testedFeature.rumContextUpdateReceivers.toSet()
759+
760+
// When
761+
testedFeature.onStop()
762+
763+
// Then
764+
rumContextUpdateReceivers.forEach {
765+
verify(mockSdkCore.removeContextUpdateReceiver(Feature.RUM_FEATURE_NAME, it))
766+
}
767+
assertThat(testedFeature.rumContextUpdateReceivers).isEmpty()
768+
}
769+
747770
@Test
748771
fun `M reset data writer W onStop()`() {
749772
// Given

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/internal/anr/ANRDetectorRunnableTest.kt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,13 @@
66

77
package com.datadog.android.rum.internal.anr
88

9-
import android.content.Context
109
import android.os.Handler
1110
import android.os.Looper
1211
import com.datadog.android.core.feature.event.ThreadDump
1312
import com.datadog.android.internal.utils.loggableStackTrace
1413
import com.datadog.android.rum.RumAttributes
1514
import com.datadog.android.rum.RumErrorSource
16-
import com.datadog.android.rum.utils.config.ApplicationContextTestConfiguration
1715
import com.datadog.android.rum.utils.config.GlobalRumMonitorTestConfiguration
18-
import com.datadog.android.rum.utils.config.MainLooperTestConfiguration
1916
import com.datadog.android.rum.utils.forge.Configurator
2017
import com.datadog.tools.unit.annotations.TestConfigurationsProvider
2118
import com.datadog.tools.unit.extensions.TestConfigurationExtension
@@ -210,14 +207,12 @@ internal class ANRDetectorRunnableTest {
210207
private const val TEST_ANR_THRESHOLD_MS = 500L
211208
private const val TEST_ANR_TEST_DELAY_MS = 50L
212209

213-
val appContext = ApplicationContextTestConfiguration(Context::class.java)
214210
val rumMonitor = GlobalRumMonitorTestConfiguration()
215-
val mainLooper = MainLooperTestConfiguration()
216211

217212
@TestConfigurationsProvider
218213
@JvmStatic
219214
fun getTestConfigurations(): List<TestConfiguration> {
220-
return listOf(appContext, rumMonitor, mainLooper)
215+
return listOf(rumMonitor)
221216
}
222217
}
223218
}

0 commit comments

Comments
 (0)