Skip to content

Commit f421a4b

Browse files
authored
Merge pull request #2888 from DataDog/tvaleev/feature/RUM-11790
RUM-11790: Supporting synthetics attribute for vital event
2 parents dfbc5aa + 7621fcb commit f421a4b

File tree

3 files changed

+175
-3
lines changed

3 files changed

+175
-3
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ internal open class RumViewScope(
344344
id = rumContext.applicationId,
345345
currentLocale = datadogContext.deviceInfo.localeInfo.currentLocale
346346
),
347+
synthetics = syntheticsAttribute,
347348
session = VitalEvent.VitalEventSession(
348349
id = rumContext.sessionId,
349350
type = sessionType,

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/assertj/VitalEventAssert.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,28 @@ internal class VitalEventAssert(actual: VitalEvent) : AbstractObjectAssert<Vital
158158
.isEqualTo(expected)
159159
}
160160

161+
fun hasNoSyntheticsTest() = apply {
162+
assertThat(actual.synthetics?.testId)
163+
.overridingErrorMessage(
164+
"Expected event to have no synthetics.testId but was ${actual.synthetics?.testId}"
165+
).isNull()
166+
assertThat(actual.synthetics?.resultId)
167+
.overridingErrorMessage(
168+
"Expected event to have no synthetics.resultId but was ${actual.synthetics?.resultId}"
169+
).isNull()
170+
}
171+
172+
fun hasSyntheticsTest(testId: String, resultId: String) = apply {
173+
assertThat(actual.synthetics?.testId)
174+
.overridingErrorMessage(
175+
"Expected event to have synthetics.testId $testId but was ${actual.synthetics?.testId}"
176+
).isEqualTo(testId)
177+
assertThat(actual.synthetics?.resultId)
178+
.overridingErrorMessage(
179+
"Expected event to have synthetics.resultId $resultId but was ${actual.synthetics?.resultId}"
180+
).isEqualTo(resultId)
181+
}
182+
161183
companion object {
162184
internal fun assertThat(actual: VitalEvent): VitalEventAssert = VitalEventAssert(actual)
163185
}

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

Lines changed: 152 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8669,11 +8669,11 @@ internal class RumViewScopeTest {
86698669
forge: Forge
86708670
) {
86718671
// Given
8672-
val operationKey = forge.aNullable { key }
8672+
val fakeOperationKey = forge.aNullable { key }
86738673
val (attributes, expectedAttributes) = withAttributesCheckingMergeWithViewAttributes(forge)
86748674
val event = RumRawEvent.StartFeatureOperation(
86758675
fakeName,
8676-
operationKey = operationKey,
8676+
operationKey = fakeOperationKey,
86778677
attributes = attributes,
86788678
eventTime = fakeEventTime + fakeDuration
86798679
)
@@ -8697,7 +8697,56 @@ internal class RumViewScopeTest {
86978697
.hasName(fakeKey.name)
86988698
.hasUrl(fakeUrl)
86998699
.hasVitalName(fakeName)
8700-
.hasVitalOperationalKey(operationKey)
8700+
.hasVitalOperationalKey(fakeOperationKey)
8701+
.hasNoSyntheticsTest()
8702+
.hasVitalStepType(VitalEvent.StepType.START)
8703+
.hasNoVitalFailureReason()
8704+
.hasVitalType(VitalEvent.VitalEventVitalType.OPERATION_STEP)
8705+
}
8706+
}
8707+
8708+
@Test
8709+
fun `M send event with synthetics info W handleEvent(VitalEvent) { StartFeatureOperation }`(
8710+
@StringForgery fakeTestId: String,
8711+
@StringForgery fakeResultId: String,
8712+
forge: Forge
8713+
) {
8714+
// Given
8715+
val fakeName = forge.anAlphabeticalString()
8716+
val fakeDuration: Long = forge.aLong(min = 0)
8717+
val fakeOperationKey = forge.aNullable { forge.anAlphabeticalString() }
8718+
val (attributes, expectedAttributes) = withAttributesCheckingMergeWithViewAttributes(forge)
8719+
val event = RumRawEvent.StartFeatureOperation(
8720+
fakeName,
8721+
operationKey = fakeOperationKey,
8722+
attributes = attributes,
8723+
eventTime = fakeEventTime + fakeDuration
8724+
)
8725+
8726+
fakeParentContext = fakeParentContext.copy(syntheticsTestId = fakeTestId, syntheticsResultId = fakeResultId)
8727+
whenever(mockParentScope.getRumContext()) doReturn fakeParentContext
8728+
8729+
// When
8730+
testedScope.handleEvent(event, fakeDatadogContext, mockEventWriteScope, mockWriter)
8731+
8732+
// Then
8733+
argumentCaptor<VitalEvent> {
8734+
verify(mockWriter).write(eq(mockEventBatchWriter), capture(), eq(EventType.DEFAULT))
8735+
VitalEventAssert.assertThat(lastValue)
8736+
.hasDate(event.eventTime.timestamp + fakeTimeInfoAtScopeStart.serverTimeOffsetMs)
8737+
.hasApplicationId(fakeParentContext.applicationId)
8738+
.containsExactlyContextAttributes(expectedAttributes)
8739+
.hasStartReason(fakeParentContext.sessionStartReason)
8740+
.hasSampleRate(fakeSampleRate)
8741+
.hasSessionId(fakeParentContext.sessionId)
8742+
.hasSessionType(fakeRumSessionType?.toVital() ?: VitalEvent.VitalEventSessionType.SYNTHETICS)
8743+
.hasSessionReplay(fakeHasReplay)
8744+
.hasViewId(testedScope.viewId)
8745+
.hasName(fakeKey.name)
8746+
.hasUrl(fakeUrl)
8747+
.hasVitalName(fakeName)
8748+
.hasVitalOperationalKey(fakeOperationKey)
8749+
.hasSyntheticsTest(fakeTestId, fakeResultId)
87018750
.hasVitalStepType(VitalEvent.StepType.START)
87028751
.hasNoVitalFailureReason()
87038752
.hasVitalType(VitalEvent.VitalEventVitalType.OPERATION_STEP)
@@ -8737,8 +8786,57 @@ internal class RumViewScopeTest {
87378786
.hasSessionId(fakeParentContext.sessionId)
87388787
.hasSessionType(fakeRumSessionType?.toVital() ?: VitalEvent.VitalEventSessionType.USER)
87398788
.hasSessionReplay(fakeHasReplay)
8789+
.hasNoSyntheticsTest()
8790+
.hasViewId(testedScope.viewId)
8791+
.hasName(fakeKey.name)
8792+
.hasUrl(fakeUrl)
8793+
.hasVitalName(fakeName)
8794+
.hasVitalOperationalKey(fakeOperationKey)
8795+
.hasVitalStepType(VitalEvent.StepType.END)
8796+
.hasNoVitalFailureReason()
8797+
.hasVitalType(VitalEvent.VitalEventVitalType.OPERATION_STEP)
8798+
}
8799+
}
8800+
8801+
@Test
8802+
fun `M send event with synthetics info W handleEvent(VitalEvent) { StopFeatureOperation, succeed }`(
8803+
@StringForgery fakeTestId: String,
8804+
@StringForgery fakeResultId: String,
8805+
forge: Forge
8806+
) {
8807+
// Given
8808+
val fakeName = forge.anAlphabeticalString()
8809+
val fakeDuration: Long = forge.aLong(min = 0)
8810+
val fakeOperationKey = forge.aNullable { forge.anAlphabeticalString() }
8811+
val (attributes, expectedAttributes) = withAttributesCheckingMergeWithViewAttributes(forge)
8812+
val event = RumRawEvent.StopFeatureOperation(
8813+
fakeName,
8814+
operationKey = fakeOperationKey,
8815+
attributes = attributes,
8816+
failureReason = null,
8817+
eventTime = fakeEventTime + fakeDuration
8818+
)
8819+
fakeParentContext = fakeParentContext.copy(syntheticsTestId = fakeTestId, syntheticsResultId = fakeResultId)
8820+
whenever(mockParentScope.getRumContext()) doReturn fakeParentContext
8821+
8822+
// When
8823+
testedScope.handleEvent(event, fakeDatadogContext, mockEventWriteScope, mockWriter)
8824+
8825+
// Then
8826+
argumentCaptor<VitalEvent> {
8827+
verify(mockWriter).write(eq(mockEventBatchWriter), capture(), eq(EventType.DEFAULT))
8828+
VitalEventAssert.assertThat(lastValue)
8829+
.hasDate(event.eventTime.timestamp + fakeTimeInfoAtScopeStart.serverTimeOffsetMs)
8830+
.hasApplicationId(fakeParentContext.applicationId)
8831+
.containsExactlyContextAttributes(expectedAttributes)
8832+
.hasStartReason(fakeParentContext.sessionStartReason)
8833+
.hasSampleRate(fakeSampleRate)
8834+
.hasSessionId(fakeParentContext.sessionId)
8835+
.hasSessionType(fakeRumSessionType?.toVital() ?: VitalEvent.VitalEventSessionType.SYNTHETICS)
8836+
.hasSessionReplay(fakeHasReplay)
87408837
.hasViewId(testedScope.viewId)
87418838
.hasName(fakeKey.name)
8839+
.hasSyntheticsTest(fakeTestId, fakeResultId)
87428840
.hasUrl(fakeUrl)
87438841
.hasVitalName(fakeName)
87448842
.hasVitalOperationalKey(fakeOperationKey)
@@ -8783,6 +8881,57 @@ internal class RumViewScopeTest {
87838881
.hasSessionType(fakeRumSessionType?.toVital() ?: VitalEvent.VitalEventSessionType.USER)
87848882
.hasSessionReplay(fakeHasReplay)
87858883
.hasViewId(testedScope.viewId)
8884+
.hasNoSyntheticsTest()
8885+
.hasName(fakeKey.name)
8886+
.hasUrl(fakeUrl)
8887+
.hasVitalName(fakeName)
8888+
.hasVitalOperationalKey(fakeOperationKey)
8889+
.hasVitalStepType(VitalEvent.StepType.END)
8890+
.hasVitalFailureReason(failureReason)
8891+
.hasVitalType(VitalEvent.VitalEventVitalType.OPERATION_STEP)
8892+
}
8893+
}
8894+
8895+
@Test
8896+
fun `M send event with synthetics info W handleEvent(VitalEvent) { StopFeatureOperation, failed }`(
8897+
@StringForgery fakeTestId: String,
8898+
@StringForgery fakeResultId: String,
8899+
forge: Forge
8900+
) {
8901+
// Given
8902+
val fakeName = forge.anAlphabeticalString()
8903+
val fakeDuration: Long = forge.aLong(min = 0)
8904+
val fakeOperationKey = forge.aNullable { forge.anAlphabeticalString() }
8905+
val (attributes, expectedAttributes) = withAttributesCheckingMergeWithViewAttributes(forge)
8906+
val failureReason = forge.aValueFrom(FailureReason::class.java)
8907+
val event = RumRawEvent.StopFeatureOperation(
8908+
fakeName,
8909+
operationKey = fakeOperationKey,
8910+
attributes = attributes,
8911+
failureReason = failureReason,
8912+
eventTime = fakeEventTime + fakeDuration
8913+
)
8914+
8915+
fakeParentContext = fakeParentContext.copy(syntheticsTestId = fakeTestId, syntheticsResultId = fakeResultId)
8916+
whenever(mockParentScope.getRumContext()) doReturn fakeParentContext
8917+
8918+
// When
8919+
testedScope.handleEvent(event, fakeDatadogContext, mockEventWriteScope, mockWriter)
8920+
8921+
// Then
8922+
argumentCaptor<VitalEvent> {
8923+
verify(mockWriter).write(eq(mockEventBatchWriter), capture(), eq(EventType.DEFAULT))
8924+
VitalEventAssert.assertThat(lastValue)
8925+
.hasDate(event.eventTime.timestamp + fakeTimeInfoAtScopeStart.serverTimeOffsetMs)
8926+
.hasApplicationId(fakeParentContext.applicationId)
8927+
.containsExactlyContextAttributes(expectedAttributes)
8928+
.hasStartReason(fakeParentContext.sessionStartReason)
8929+
.hasSampleRate(fakeSampleRate)
8930+
.hasSyntheticsTest(fakeTestId, fakeResultId)
8931+
.hasSessionId(fakeParentContext.sessionId)
8932+
.hasSessionType(fakeRumSessionType?.toVital() ?: VitalEvent.VitalEventSessionType.SYNTHETICS)
8933+
.hasSessionReplay(fakeHasReplay)
8934+
.hasViewId(testedScope.viewId)
87868935
.hasName(fakeKey.name)
87878936
.hasUrl(fakeUrl)
87888937
.hasVitalName(fakeName)

0 commit comments

Comments
 (0)