Skip to content

Commit

Permalink
RUM-2127 Add synthetics info to RUM Resources
Browse files Browse the repository at this point in the history
  • Loading branch information
xgouchet committed Nov 15, 2023
1 parent 05f41b9 commit c99618c
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,22 @@ internal class RumResourceScope(
val rulePsr = attributes.remove(RumAttributes.RULE_PSR) as? Number

val rumContext = getRumContext()
val syntheticsAttribute = if (
rumContext.syntheticsTestId.isNullOrBlank() ||
rumContext.syntheticsResultId.isNullOrBlank()
) {
null
} else {
ResourceEvent.Synthetics(
testId = rumContext.syntheticsTestId,
resultId = rumContext.syntheticsResultId
)
}
val sessionType = if (syntheticsAttribute == null) {
ResourceEvent.ResourceEventSessionType.USER
} else {
ResourceEvent.ResourceEventSessionType.SYNTHETICS
}

@Suppress("UNCHECKED_CAST")
val finalTiming = timing ?: extractResourceTiming(
Expand Down Expand Up @@ -233,9 +249,10 @@ internal class RumResourceScope(
application = ResourceEvent.Application(rumContext.applicationId),
session = ResourceEvent.ResourceEventSession(
id = rumContext.sessionId,
type = ResourceEvent.ResourceEventSessionType.USER,
type = sessionType,
hasReplay = hasReplay
),
synthetics = syntheticsAttribute,
source = ResourceEvent.Source.tryFromSource(
datadogContext.source,
sdkCore.internalLogger
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,46 @@ internal class ResourceEventAssert(actual: ResourceEvent) :
return this
}

fun hasUserSession(): ResourceEventAssert {
assertThat(actual.session.type)
.overridingErrorMessage(
"Expected event to have session.type:user but was ${actual.session.type}"
).isEqualTo(ResourceEvent.ResourceEventSessionType.USER)
return this
}

fun hasSyntheticsSession(): ResourceEventAssert {
assertThat(actual.session.type)
.overridingErrorMessage(
"Expected event to have session.type:synthetics but was ${actual.session.type}"
).isEqualTo(ResourceEvent.ResourceEventSessionType.SYNTHETICS)
return this
}

fun hasNoSyntheticsTest(): ResourceEventAssert {
assertThat(actual.synthetics?.testId)
.overridingErrorMessage(
"Expected event to have no synthetics.testId but was ${actual.synthetics?.testId}"
).isNull()
assertThat(actual.synthetics?.resultId)
.overridingErrorMessage(
"Expected event to have no synthetics.resultId but was ${actual.synthetics?.resultId}"
).isNull()
return this
}

fun hasSyntheticsTest(testId: String, resultId: String): ResourceEventAssert {
assertThat(actual.synthetics?.testId)
.overridingErrorMessage(
"Expected event to have synthetics.testId $testId but was ${actual.synthetics?.testId}"
).isEqualTo(testId)
assertThat(actual.synthetics?.resultId)
.overridingErrorMessage(
"Expected event to have synthetics.resultId $resultId but was ${actual.synthetics?.resultId}"
).isEqualTo(resultId)
return this
}

fun hasActionId(expected: String?): ResourceEventAssert {
if (expected != null) {
assertThat(actual.action?.id)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,8 @@ internal class RumResourceScopeTest {
hasReplay(fakeHasReplay)
hasRulePsr(null)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
containsExactlyContextAttributes(expectedAttributes)
hasSource(fakeSourceResourceEvent)
Expand Down Expand Up @@ -335,6 +337,8 @@ internal class RumResourceScopeTest {
hasProviderType(ResourceEvent.ProviderType.FIRST_PARTY)
hasProviderDomain(URL(fakeUrl).host)
hasLiteSessionPlan()
hasUserSession()
hasNoSyntheticsTest()
containsExactlyContextAttributes(expectedAttributes)
hasSource(fakeSourceResourceEvent)
hasDeviceInfo(
Expand Down Expand Up @@ -417,6 +421,8 @@ internal class RumResourceScopeTest {
hasProviderType(ResourceEvent.ProviderType.FIRST_PARTY)
hasProviderDomain(brokenUrl)
hasLiteSessionPlan()
hasUserSession()
hasNoSyntheticsTest()
containsExactlyContextAttributes(expectedAttributes)
hasSource(fakeSourceResourceEvent)
hasDeviceInfo(
Expand Down Expand Up @@ -489,6 +495,8 @@ internal class RumResourceScopeTest {
hasReplay(fakeHasReplay)
hasRulePsr(fakeRulePsr)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
containsExactlyContextAttributes(expectedAttributes)
hasSource(fakeSourceResourceEvent)
Expand Down Expand Up @@ -557,6 +565,96 @@ internal class RumResourceScopeTest {
hasReplay(fakeHasReplay)
hasRulePsr(null)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
containsExactlyContextAttributes(expectedAttributes)
hasSource(fakeSourceResourceEvent)
hasDeviceInfo(
fakeDatadogContext.deviceInfo.deviceName,
fakeDatadogContext.deviceInfo.deviceModel,
fakeDatadogContext.deviceInfo.deviceBrand,
fakeDatadogContext.deviceInfo.deviceType.toResourceSchemaType(),
fakeDatadogContext.deviceInfo.architecture
)
hasOsInfo(
fakeDatadogContext.deviceInfo.osName,
fakeDatadogContext.deviceInfo.osVersion,
fakeDatadogContext.deviceInfo.osMajorVersion
)
hasServiceName(fakeDatadogContext.service)
hasVersion(fakeDatadogContext.version)
hasSampleRate(fakeSampleRate)
}
}
verify(mockParentScope, never()).handleEvent(any(), any())
verifyNoMoreInteractions(mockWriter)
assertThat(result).isEqualTo(null)
}

@Test
fun `𝕄 send Resource with synthetics info context 𝕎 handleEvent(StopResource)`(
@StringForgery fakeTestId: String,
@StringForgery fakeResultId: String,
@Forgery kind: RumResourceKind,
@LongForgery(200, 600) statusCode: Long,
@LongForgery(0, 1024) size: Long,
forge: Forge
) {
// Given
val attributes = forge.exhaustiveAttributes(excludedKeys = fakeAttributes.keys)
val expectedAttributes = mutableMapOf<String, Any?>()
expectedAttributes.putAll(fakeAttributes)
expectedAttributes.putAll(attributes)
fakeParentContext = fakeParentContext.copy(
syntheticsTestId = fakeTestId,
syntheticsResultId = fakeResultId
)
whenever(mockParentScope.getRumContext()) doReturn fakeParentContext
testedScope = RumResourceScope(
mockParentScope,
rumMonitor.mockSdkCore,
fakeUrl,
fakeMethod,
fakeKey,
fakeEventTime,
fakeAttributes,
fakeServerOffset,
mockResolver,
mockFeaturesContextResolver,
fakeSampleRate
)

// When
Thread.sleep(RESOURCE_DURATION_MS)
mockEvent = RumRawEvent.StopResource(fakeKey, statusCode, size, kind, attributes)
val result = testedScope.handleEvent(mockEvent, mockWriter)

// Then
argumentCaptor<ResourceEvent> {
verify(mockWriter).write(eq(mockEventBatchWriter), capture())
assertThat(firstValue)
.apply {
hasId(testedScope.resourceId)
hasTimestamp(resolveExpectedTimestamp())
hasUrl(fakeUrl)
hasMethod(fakeMethod)
hasKind(kind)
hasStatusCode(statusCode)
hasDurationGreaterThan(TimeUnit.MILLISECONDS.toNanos(RESOURCE_DURATION_MS))
hasUserInfo(fakeDatadogContext.userInfo)
hasConnectivityInfo(fakeNetworkInfoAtScopeStart)
hasView(fakeParentContext)
hasApplicationId(fakeParentContext.applicationId)
hasSessionId(fakeParentContext.sessionId)
hasActionId(fakeParentContext.actionId)
hasTraceId(null)
hasSpanId(null)
hasReplay(fakeHasReplay)
hasRulePsr(null)
doesNotHaveAResourceProvider()
hasSyntheticsSession()
hasSyntheticsTest(fakeTestId, fakeResultId)
hasLiteSessionPlan()
containsExactlyContextAttributes(expectedAttributes)
hasSource(fakeSourceResourceEvent)
Expand Down Expand Up @@ -616,6 +714,8 @@ internal class RumResourceScopeTest {
hasReplay(fakeHasReplay)
hasRulePsr(null)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
containsExactlyContextAttributes(fakeAttributes)
hasSource(fakeSourceResourceEvent)
Expand Down Expand Up @@ -666,6 +766,8 @@ internal class RumResourceScopeTest {
hasSessionId(fakeParentContext.sessionId)
hasActionId(fakeParentContext.actionId)
hasLiteSessionPlan()
hasUserSession()
hasNoSyntheticsTest()
hasReplay(fakeHasReplay)
containsExactlyContextAttributes(fakeAttributes)
hasSource(fakeSourceResourceEvent)
Expand Down Expand Up @@ -790,6 +892,8 @@ internal class RumResourceScopeTest {
hasReplay(fakeHasReplay)
hasRulePsr(null)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
containsExactlyContextAttributes(expectedAttributes)
hasSource(fakeSourceResourceEvent)
Expand Down Expand Up @@ -859,6 +963,8 @@ internal class RumResourceScopeTest {
hasReplay(fakeHasReplay)
hasRulePsr(null)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
containsExactlyContextAttributes(expectedAttributes)
hasSource(fakeSourceResourceEvent)
Expand Down Expand Up @@ -929,6 +1035,8 @@ internal class RumResourceScopeTest {
hasReplay(fakeHasReplay)
hasRulePsr(null)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
containsExactlyContextAttributes(expectedAttributes)
hasSource(fakeSourceResourceEvent)
Expand Down Expand Up @@ -1000,6 +1108,8 @@ internal class RumResourceScopeTest {
hasReplay(fakeHasReplay)
hasRulePsr(null)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
containsExactlyContextAttributes(expectedAttributes)
hasSource(fakeSourceResourceEvent)
Expand Down Expand Up @@ -2129,6 +2239,8 @@ internal class RumResourceScopeTest {
hasSessionId(fakeParentContext.sessionId)
hasActionId(fakeParentContext.actionId)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
hasReplay(fakeHasReplay)
containsExactlyContextAttributes(expectedAttributes)
Expand Down Expand Up @@ -2194,6 +2306,8 @@ internal class RumResourceScopeTest {
hasSessionId(fakeParentContext.sessionId)
hasActionId(fakeParentContext.actionId)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
hasReplay(fakeHasReplay)
containsExactlyContextAttributes(expectedAttributes)
Expand Down Expand Up @@ -2261,6 +2375,8 @@ internal class RumResourceScopeTest {
hasSessionId(fakeParentContext.sessionId)
hasActionId(fakeParentContext.actionId)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
hasReplay(fakeHasReplay)
containsExactlyContextAttributes(expectedAttributes)
Expand Down Expand Up @@ -2377,6 +2493,8 @@ internal class RumResourceScopeTest {
hasSessionId(fakeParentContext.sessionId)
hasActionId(fakeParentContext.actionId)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
hasReplay(fakeHasReplay)
hasSource(fakeSourceResourceEvent)
Expand Down Expand Up @@ -2442,6 +2560,8 @@ internal class RumResourceScopeTest {
hasSessionId(fakeParentContext.sessionId)
hasActionId(fakeParentContext.actionId)
doesNotHaveAResourceProvider()
hasUserSession()
hasNoSyntheticsTest()
hasLiteSessionPlan()
hasReplay(fakeHasReplay)
hasSource(fakeSourceResourceEvent)
Expand Down

0 comments on commit c99618c

Please sign in to comment.