Skip to content

Commit 2fe6c41

Browse files
authored
Merge pull request #2655 from DataDog/xgouchet/RUM-9908/add_view_attributes_update_methods
RUM-9908 Create view attributes update methods
2 parents 71b124b + a4a2645 commit 2fe6c41

File tree

9 files changed

+144
-0
lines changed

9 files changed

+144
-0
lines changed

features/dd-sdk-android-rum/api/apiSurface

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ interface com.datadog.android.rum.RumMonitor
120120
fun clearAttributes()
121121
fun stopSession()
122122
fun addViewLoadingTime(Boolean)
123+
fun addViewAttributes(Map<String, Any?>)
124+
fun removeViewAttributes(Collection<String>)
123125
var debug: Boolean
124126
fun _getInternal(): _RumInternalProxy?
125127
enum com.datadog.android.rum.RumPerformanceMetric

features/dd-sdk-android-rum/api/dd-sdk-android-rum.api

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,14 @@ public abstract interface class com/datadog/android/rum/RumMonitor {
152152
public abstract fun addFeatureFlagEvaluation (Ljava/lang/String;Ljava/lang/Object;)V
153153
public abstract fun addFeatureFlagEvaluations (Ljava/util/Map;)V
154154
public abstract fun addTiming (Ljava/lang/String;)V
155+
public abstract fun addViewAttributes (Ljava/util/Map;)V
155156
public abstract fun addViewLoadingTime (Z)V
156157
public abstract fun clearAttributes ()V
157158
public abstract fun getAttributes ()Ljava/util/Map;
158159
public abstract fun getCurrentSessionId (Lkotlin/jvm/functions/Function1;)V
159160
public abstract fun getDebug ()Z
160161
public abstract fun removeAttribute (Ljava/lang/String;)V
162+
public abstract fun removeViewAttributes (Ljava/util/Collection;)V
161163
public abstract fun setDebug (Z)V
162164
public abstract fun startAction (Lcom/datadog/android/rum/RumActionType;Ljava/lang/String;Ljava/util/Map;)V
163165
public abstract fun startResource (Ljava/lang/String;Lcom/datadog/android/rum/RumResourceMethod;Ljava/lang/String;Ljava/util/Map;)V

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,20 @@ interface RumMonitor {
334334
@ExperimentalRumApi
335335
fun addViewLoadingTime(overwrite: Boolean)
336336

337+
/**
338+
* Adds attributes to the current active View. They will be propagated to all future RUM events within this View
339+
* until it stops being active.
340+
* @param attributes the attributes to add to the view
341+
*/
342+
fun addViewAttributes(attributes: Map<String, Any?>)
343+
344+
/**
345+
* Removes attributes from the current active View. Future RUM events within this view won't be having these
346+
* attributes anymore.
347+
* @param attributes the attribute keys to remove from the view
348+
*/
349+
fun removeViewAttributes(attributes: Collection<String>)
350+
337351
/**
338352
* Utility setting to inspect the active RUM View.
339353
* If set, a debugging outline will be displayed on top of the application, describing the name

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumApplicationScope.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,12 +122,16 @@ internal class RumApplicationScope(
122122

123123
// endregion
124124

125+
// region RumViewChangedListener
126+
125127
override fun onViewChanged(viewInfo: RumViewInfo) {
126128
if (viewInfo.isActive) {
127129
lastActiveViewInfo = viewInfo
128130
}
129131
}
130132

133+
// endregion
134+
131135
// region Internal
132136

133137
@WorkerThread

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumRawEvent.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,16 @@ internal sealed class RumRawEvent {
186186
override val eventTime: Time = Time()
187187
) : RumRawEvent()
188188

189+
internal data class AddViewAttributes(
190+
val attributes: Map<String, Any?>,
191+
override val eventTime: Time = Time()
192+
) : RumRawEvent()
193+
194+
internal data class RemoveViewAttributes(
195+
val attributes: Collection<String>,
196+
override val eventTime: Time = Time()
197+
) : RumRawEvent()
198+
189199
internal data class AddLongTask(
190200
val durationNs: Long,
191201
val target: String,

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScope.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,8 @@ internal open class RumViewScope(
216216

217217
is RumRawEvent.UpdatePerformanceMetric -> onUpdatePerformanceMetric(event)
218218
is RumRawEvent.AddViewLoadingTime -> onAddViewLoadingTime(event, writer)
219+
is RumRawEvent.AddViewAttributes -> onAddViewAttributes(event)
220+
is RumRawEvent.RemoveViewAttributes -> onRemoveViewAttributes(event)
219221

220222
else -> delegateEventToChildren(event, writer)
221223
}
@@ -322,6 +324,18 @@ internal open class RumViewScope(
322324
sendViewUpdate(event, writer)
323325
}
324326

327+
@WorkerThread
328+
private fun onAddViewAttributes(event: RumRawEvent.AddViewAttributes) {
329+
viewAttributes.putAll(event.attributes)
330+
}
331+
332+
@WorkerThread
333+
private fun onRemoveViewAttributes(event: RumRawEvent.RemoveViewAttributes) {
334+
event.attributes.forEach {
335+
viewAttributes.remove(it)
336+
}
337+
}
338+
325339
@WorkerThread
326340
private fun onStartView(
327341
event: RumRawEvent.StartView,

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,18 @@ internal class DatadogRumMonitor(
553553
handleEvent(RumRawEvent.AddViewLoadingTime(overwrite = overwrite))
554554
}
555555

556+
override fun addViewAttributes(attributes: Map<String, Any?>) {
557+
handleEvent(
558+
RumRawEvent.AddViewAttributes(attributes)
559+
)
560+
}
561+
562+
override fun removeViewAttributes(attributes: Collection<String>) {
563+
handleEvent(
564+
RumRawEvent.RemoveViewAttributes(attributes)
565+
)
566+
}
567+
556568
override fun addLongTask(durationNs: Long, target: String) {
557569
handleEvent(
558570
RumRawEvent.AddLongTask(durationNs, target)

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/internal/domain/scope/RumViewScopeAttributePropagationTest.kt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,13 @@ import com.datadog.tools.unit.extensions.TestConfigurationExtension
4545
import com.datadog.tools.unit.extensions.config.TestConfiguration
4646
import com.datadog.tools.unit.forge.exhaustiveAttributes
4747
import fr.xgouchet.elmyr.Forge
48+
import fr.xgouchet.elmyr.annotation.AdvancedForgery
4849
import fr.xgouchet.elmyr.annotation.BoolForgery
4950
import fr.xgouchet.elmyr.annotation.Forgery
5051
import fr.xgouchet.elmyr.annotation.LongForgery
52+
import fr.xgouchet.elmyr.annotation.MapForgery
5153
import fr.xgouchet.elmyr.annotation.StringForgery
54+
import fr.xgouchet.elmyr.annotation.StringForgeryType
5255
import fr.xgouchet.elmyr.junit5.ForgeConfiguration
5356
import fr.xgouchet.elmyr.junit5.ForgeExtension
5457
import org.assertj.core.api.Assertions.assertThat
@@ -314,6 +317,52 @@ internal class RumViewScopeAttributePropagationTest {
314317
}
315318
}
316319

320+
@Test
321+
fun `M send event with added view attributes W handleEvent(AddViewAttributes+KeepAlive) on active view`() {
322+
// Given
323+
val expectedAttributes = mutableMapOf<String, Any?>()
324+
expectedAttributes.putAll(fakeParentAttributes)
325+
expectedAttributes.putAll(fakeViewAttributes)
326+
testedScope = newRumViewScope(initialAttributes = emptyMap())
327+
328+
// When
329+
testedScope.handleEvent(RumRawEvent.AddViewAttributes(fakeViewAttributes), mockWriter)
330+
val result = testedScope.handleEvent(RumRawEvent.KeepAlive(), mockWriter)
331+
332+
// Then
333+
argumentCaptor<ViewEvent> {
334+
verify(mockWriter).write(eq(mockEventBatchWriter), capture(), eq(EventType.DEFAULT))
335+
assertThat(lastValue)
336+
.containsExactlyContextAttributes(expectedAttributes)
337+
}
338+
assertThat(result).isNotNull()
339+
}
340+
341+
@Test
342+
fun `M send event without removed view attributes W handleEvent(AddViewAttributes+KeepAlive) on active view`(
343+
@MapForgery(
344+
key = AdvancedForgery(string = [StringForgery(StringForgeryType.ALPHABETICAL)]),
345+
value = AdvancedForgery(string = [StringForgery()])
346+
) fakeViewAttributes: Map<String, String>
347+
) {
348+
// Given
349+
val expectedAttributes = mutableMapOf<String, Any?>()
350+
expectedAttributes.putAll(fakeParentAttributes)
351+
testedScope = newRumViewScope(initialAttributes = fakeViewAttributes)
352+
353+
// When
354+
testedScope.handleEvent(RumRawEvent.RemoveViewAttributes(fakeViewAttributes.keys), mockWriter)
355+
val result = testedScope.handleEvent(RumRawEvent.KeepAlive(), mockWriter)
356+
357+
// Then
358+
argumentCaptor<ViewEvent> {
359+
verify(mockWriter).write(eq(mockEventBatchWriter), capture(), eq(EventType.DEFAULT))
360+
assertThat(lastValue)
361+
.containsExactlyContextAttributes(expectedAttributes)
362+
}
363+
assertThat(result).isNotNull()
364+
}
365+
317366
// endregion
318367

319368
// region Propagate parent attributes in Error Event

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

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,14 @@ import com.datadog.android.telemetry.internal.TelemetryEventHandler
5555
import com.datadog.tools.unit.forge.aThrowable
5656
import com.datadog.tools.unit.forge.exhaustiveAttributes
5757
import fr.xgouchet.elmyr.Forge
58+
import fr.xgouchet.elmyr.annotation.AdvancedForgery
5859
import fr.xgouchet.elmyr.annotation.BoolForgery
5960
import fr.xgouchet.elmyr.annotation.DoubleForgery
6061
import fr.xgouchet.elmyr.annotation.FloatForgery
6162
import fr.xgouchet.elmyr.annotation.Forgery
6263
import fr.xgouchet.elmyr.annotation.IntForgery
6364
import fr.xgouchet.elmyr.annotation.LongForgery
65+
import fr.xgouchet.elmyr.annotation.MapForgery
6466
import fr.xgouchet.elmyr.annotation.StringForgery
6567
import fr.xgouchet.elmyr.annotation.StringForgeryType
6668
import fr.xgouchet.elmyr.junit5.ForgeConfiguration
@@ -919,6 +921,41 @@ internal class DatadogRumMonitorTest {
919921
verifyNoMoreInteractions(mockScope, mockWriter)
920922
}
921923

924+
@Test
925+
fun `M delegate event to rootScope W addViewAttributes()`(
926+
@MapForgery(
927+
key = AdvancedForgery(string = [StringForgery(StringForgeryType.ALPHABETICAL)]),
928+
value = AdvancedForgery(string = [StringForgery()])
929+
) fakeAttributes: Map<String, String>
930+
) {
931+
testedMonitor.addViewAttributes(fakeAttributes)
932+
Thread.sleep(PROCESSING_DELAY)
933+
934+
argumentCaptor<RumRawEvent> {
935+
verify(mockScope).handleEvent(capture(), same(mockWriter))
936+
val event = firstValue
937+
check(event is RumRawEvent.AddViewAttributes)
938+
assertThat(event.attributes).isSameAs(fakeAttributes)
939+
}
940+
verifyNoMoreInteractions(mockScope, mockWriter)
941+
}
942+
943+
@Test
944+
fun `M delegate event to rootScope W removeViewAttributes()`(
945+
@StringForgery fakeAttributes: List<String>
946+
) {
947+
testedMonitor.removeViewAttributes(fakeAttributes)
948+
Thread.sleep(PROCESSING_DELAY)
949+
950+
argumentCaptor<RumRawEvent> {
951+
verify(mockScope).handleEvent(capture(), same(mockWriter))
952+
val event = firstValue
953+
check(event is RumRawEvent.RemoveViewAttributes)
954+
assertThat(event.attributes).isSameAs(fakeAttributes)
955+
}
956+
verifyNoMoreInteractions(mockScope, mockWriter)
957+
}
958+
922959
@Test
923960
fun `M delegate event to rootScope on current thread W addCrash()`(
924961
@StringForgery message: String,

0 commit comments

Comments
 (0)