Skip to content

Commit

Permalink
Merge pull request #1758 from DataDog/xgouchet/RUM-451/rum_apm_attrib…
Browse files Browse the repository at this point in the history
…utes

RUM-451 Update RUM attributes in spans
  • Loading branch information
xgouchet authored Dec 11, 2023
2 parents 538dd22 + 152d1ce commit b3779e4
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 18 deletions.
20 changes: 19 additions & 1 deletion features/dd-sdk-android-trace/api/apiSurface
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ data class com.datadog.android.trace.model.SpanEvent
fun fromJson(kotlin.String): Meta
fun fromJsonObject(com.google.gson.JsonObject): Meta
data class Dd
constructor(kotlin.String? = "android")
constructor(kotlin.String? = "android", Application? = null, Session? = null, View? = null)
fun toJson(): com.google.gson.JsonElement
companion object
fun fromJson(kotlin.String): Dd
Expand All @@ -74,6 +74,24 @@ data class com.datadog.android.trace.model.SpanEvent
companion object
fun fromJson(kotlin.String): Network
fun fromJsonObject(com.google.gson.JsonObject): Network
data class Application
constructor(kotlin.String? = null)
fun toJson(): com.google.gson.JsonElement
companion object
fun fromJson(kotlin.String): Application
fun fromJsonObject(com.google.gson.JsonObject): Application
data class Session
constructor(kotlin.String? = null)
fun toJson(): com.google.gson.JsonElement
companion object
fun fromJson(kotlin.String): Session
fun fromJsonObject(com.google.gson.JsonObject): Session
data class View
constructor(kotlin.String? = null)
fun toJson(): com.google.gson.JsonElement
companion object
fun fromJson(kotlin.String): View
fun fromJsonObject(com.google.gson.JsonObject): View
data class Client
constructor(SimCarrier? = null, kotlin.String? = null, kotlin.String? = null, kotlin.String? = null, kotlin.String? = null)
fun toJson(): com.google.gson.JsonElement
Expand Down
80 changes: 76 additions & 4 deletions features/dd-sdk-android-trace/api/dd-sdk-android-trace.api
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,28 @@ public final class com/datadog/android/trace/model/SpanEvent {
public fun toString ()Ljava/lang/String;
}

public final class com/datadog/android/trace/model/SpanEvent$Application {
public static final field Companion Lcom/datadog/android/trace/model/SpanEvent$Application$Companion;
public fun <init> ()V
public fun <init> (Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;)Lcom/datadog/android/trace/model/SpanEvent$Application;
public static synthetic fun copy$default (Lcom/datadog/android/trace/model/SpanEvent$Application;Ljava/lang/String;ILjava/lang/Object;)Lcom/datadog/android/trace/model/SpanEvent$Application;
public fun equals (Ljava/lang/Object;)Z
public static final fun fromJson (Ljava/lang/String;)Lcom/datadog/android/trace/model/SpanEvent$Application;
public static final fun fromJsonObject (Lcom/google/gson/JsonObject;)Lcom/datadog/android/trace/model/SpanEvent$Application;
public final fun getId ()Ljava/lang/String;
public fun hashCode ()I
public final fun toJson ()Lcom/google/gson/JsonElement;
public fun toString ()Ljava/lang/String;
}

public final class com/datadog/android/trace/model/SpanEvent$Application$Companion {
public final fun fromJson (Ljava/lang/String;)Lcom/datadog/android/trace/model/SpanEvent$Application;
public final fun fromJsonObject (Lcom/google/gson/JsonObject;)Lcom/datadog/android/trace/model/SpanEvent$Application;
}

public final class com/datadog/android/trace/model/SpanEvent$Client {
public static final field Companion Lcom/datadog/android/trace/model/SpanEvent$Client$Companion;
public fun <init> ()V
Expand Down Expand Up @@ -137,15 +159,21 @@ public final class com/datadog/android/trace/model/SpanEvent$Companion {
public final class com/datadog/android/trace/model/SpanEvent$Dd {
public static final field Companion Lcom/datadog/android/trace/model/SpanEvent$Dd$Companion;
public fun <init> ()V
public fun <init> (Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/lang/String;Lcom/datadog/android/trace/model/SpanEvent$Application;Lcom/datadog/android/trace/model/SpanEvent$Session;Lcom/datadog/android/trace/model/SpanEvent$View;)V
public synthetic fun <init> (Ljava/lang/String;Lcom/datadog/android/trace/model/SpanEvent$Application;Lcom/datadog/android/trace/model/SpanEvent$Session;Lcom/datadog/android/trace/model/SpanEvent$View;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;)Lcom/datadog/android/trace/model/SpanEvent$Dd;
public static synthetic fun copy$default (Lcom/datadog/android/trace/model/SpanEvent$Dd;Ljava/lang/String;ILjava/lang/Object;)Lcom/datadog/android/trace/model/SpanEvent$Dd;
public final fun component2 ()Lcom/datadog/android/trace/model/SpanEvent$Application;
public final fun component3 ()Lcom/datadog/android/trace/model/SpanEvent$Session;
public final fun component4 ()Lcom/datadog/android/trace/model/SpanEvent$View;
public final fun copy (Ljava/lang/String;Lcom/datadog/android/trace/model/SpanEvent$Application;Lcom/datadog/android/trace/model/SpanEvent$Session;Lcom/datadog/android/trace/model/SpanEvent$View;)Lcom/datadog/android/trace/model/SpanEvent$Dd;
public static synthetic fun copy$default (Lcom/datadog/android/trace/model/SpanEvent$Dd;Ljava/lang/String;Lcom/datadog/android/trace/model/SpanEvent$Application;Lcom/datadog/android/trace/model/SpanEvent$Session;Lcom/datadog/android/trace/model/SpanEvent$View;ILjava/lang/Object;)Lcom/datadog/android/trace/model/SpanEvent$Dd;
public fun equals (Ljava/lang/Object;)Z
public static final fun fromJson (Ljava/lang/String;)Lcom/datadog/android/trace/model/SpanEvent$Dd;
public static final fun fromJsonObject (Lcom/google/gson/JsonObject;)Lcom/datadog/android/trace/model/SpanEvent$Dd;
public final fun getApplication ()Lcom/datadog/android/trace/model/SpanEvent$Application;
public final fun getSession ()Lcom/datadog/android/trace/model/SpanEvent$Session;
public final fun getSource ()Ljava/lang/String;
public final fun getView ()Lcom/datadog/android/trace/model/SpanEvent$View;
public fun hashCode ()I
public final fun toJson ()Lcom/google/gson/JsonElement;
public fun toString ()Ljava/lang/String;
Expand Down Expand Up @@ -235,6 +263,28 @@ public final class com/datadog/android/trace/model/SpanEvent$Network$Companion {
public final fun fromJsonObject (Lcom/google/gson/JsonObject;)Lcom/datadog/android/trace/model/SpanEvent$Network;
}

public final class com/datadog/android/trace/model/SpanEvent$Session {
public static final field Companion Lcom/datadog/android/trace/model/SpanEvent$Session$Companion;
public fun <init> ()V
public fun <init> (Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;)Lcom/datadog/android/trace/model/SpanEvent$Session;
public static synthetic fun copy$default (Lcom/datadog/android/trace/model/SpanEvent$Session;Ljava/lang/String;ILjava/lang/Object;)Lcom/datadog/android/trace/model/SpanEvent$Session;
public fun equals (Ljava/lang/Object;)Z
public static final fun fromJson (Ljava/lang/String;)Lcom/datadog/android/trace/model/SpanEvent$Session;
public static final fun fromJsonObject (Lcom/google/gson/JsonObject;)Lcom/datadog/android/trace/model/SpanEvent$Session;
public final fun getId ()Ljava/lang/String;
public fun hashCode ()I
public final fun toJson ()Lcom/google/gson/JsonElement;
public fun toString ()Ljava/lang/String;
}

public final class com/datadog/android/trace/model/SpanEvent$Session$Companion {
public final fun fromJson (Ljava/lang/String;)Lcom/datadog/android/trace/model/SpanEvent$Session;
public final fun fromJsonObject (Lcom/google/gson/JsonObject;)Lcom/datadog/android/trace/model/SpanEvent$Session;
}

public final class com/datadog/android/trace/model/SpanEvent$SimCarrier {
public static final field Companion Lcom/datadog/android/trace/model/SpanEvent$SimCarrier$Companion;
public fun <init> ()V
Expand Down Expand Up @@ -313,6 +363,28 @@ public final class com/datadog/android/trace/model/SpanEvent$Usr$Companion {
public final fun fromJsonObject (Lcom/google/gson/JsonObject;)Lcom/datadog/android/trace/model/SpanEvent$Usr;
}

public final class com/datadog/android/trace/model/SpanEvent$View {
public static final field Companion Lcom/datadog/android/trace/model/SpanEvent$View$Companion;
public fun <init> ()V
public fun <init> (Ljava/lang/String;)V
public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;)Lcom/datadog/android/trace/model/SpanEvent$View;
public static synthetic fun copy$default (Lcom/datadog/android/trace/model/SpanEvent$View;Ljava/lang/String;ILjava/lang/Object;)Lcom/datadog/android/trace/model/SpanEvent$View;
public fun equals (Ljava/lang/Object;)Z
public static final fun fromJson (Ljava/lang/String;)Lcom/datadog/android/trace/model/SpanEvent$View;
public static final fun fromJsonObject (Lcom/google/gson/JsonObject;)Lcom/datadog/android/trace/model/SpanEvent$View;
public final fun getId ()Ljava/lang/String;
public fun hashCode ()I
public final fun toJson ()Lcom/google/gson/JsonElement;
public fun toString ()Ljava/lang/String;
}

public final class com/datadog/android/trace/model/SpanEvent$View$Companion {
public final fun fromJson (Ljava/lang/String;)Lcom/datadog/android/trace/model/SpanEvent$View;
public final fun fromJsonObject (Lcom/google/gson/JsonObject;)Lcom/datadog/android/trace/model/SpanEvent$View;
}

public final class com/datadog/android/trace/sqlite/SqliteDatabaseExtKt {
public static final fun transactionTraced (Landroid/database/sqlite/SQLiteDatabase;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Ljava/lang/Object;
public static synthetic fun transactionTraced$default (Landroid/database/sqlite/SQLiteDatabase;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Ljava/lang/Object;
Expand Down
33 changes: 33 additions & 0 deletions features/dd-sdk-android-trace/src/main/json/trace/span-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,39 @@
"description": "The trace source",
"default": "android",
"readOnly": true
},
"application": {
"type": "object",
"description": "The RUM Application attributes",
"properties": {
"id": {
"type": "string",
"description": "RUM Application ID",
"readOnly": true
}
}
},
"session": {
"type": "object",
"description": "The active RUM Session attributes",
"properties": {
"id": {
"type": "string",
"description": "The RUM Session ID",
"readOnly": true
}
}
},
"view": {
"type": "object",
"description": "The active RUM View attributes",
"properties": {
"id": {
"type": "string",
"description": "The RUM View ID",
"readOnly": true
}
}
}
},
"readOnly": true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package com.datadog.android.trace.internal.domain.event
import com.datadog.android.api.context.DatadogContext
import com.datadog.android.api.context.NetworkInfo
import com.datadog.android.core.internal.utils.toHexString
import com.datadog.android.log.LogAttributes
import com.datadog.android.trace.model.SpanEvent
import com.datadog.opentracing.DDSpan

Expand Down Expand Up @@ -68,9 +69,15 @@ internal class DdSpanToSpanEventMapper(
email = userInfo.email,
additionalProperties = userInfo.additionalProperties.toMutableMap()
)
val dd = SpanEvent.Dd(
source = datadogContext.source,
application = event.tags[LogAttributes.RUM_APPLICATION_ID]?.let { SpanEvent.Application(it as? String) },
session = event.tags[LogAttributes.RUM_SESSION_ID]?.let { SpanEvent.Session(it as? String) },
view = event.tags[LogAttributes.RUM_VIEW_ID]?.let { SpanEvent.View(it as? String) }
)
return SpanEvent.Meta(
version = datadogContext.version,
dd = SpanEvent.Dd(source = datadogContext.source),
dd = dd,
span = SpanEvent.Span(),
tracer = SpanEvent.Tracer(
version = datadogContext.sdkVersion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,43 @@ internal class SpanEventAssert(actual: SpanEvent) :
fun hasSpanSource(spanSource: String): SpanEventAssert {
assertThat(actual.meta.dd.source)
.overridingErrorMessage(
"Expected SpanEvent to have source: $spanSource" +
"Expected SpanEvent to have _dd.source: $spanSource" +
" but instead was: ${actual.meta.dd.source}"
)
.isEqualTo(spanSource)
return this
}

fun hasApplicationId(applicationId: String?): SpanEventAssert {
assertThat(actual.meta.dd.application?.id)
.overridingErrorMessage(
"Expected SpanEvent to have _dd.application.id: $applicationId" +
" but instead was: ${actual.meta.dd.application?.id}"
)
.isEqualTo(applicationId)
return this
}

fun hasSessionId(sessionId: String?): SpanEventAssert {
assertThat(actual.meta.dd.session?.id)
.overridingErrorMessage(
"Expected SpanEvent to have _dd.session.id: $sessionId" +
" but instead was: ${actual.meta.dd.session?.id}"
)
.isEqualTo(sessionId)
return this
}

fun hasViewId(viewId: String?): SpanEventAssert {
assertThat(actual.meta.dd.view?.id)
.overridingErrorMessage(
"Expected SpanEvent to have _dd.view.id: $viewId" +
" but instead was: ${actual.meta.dd.view?.id}"
)
.isEqualTo(viewId)
return this
}

fun hasSpanStartTime(startTime: Long): SpanEventAssert {
assertThat(actual.start)
.overridingErrorMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ package com.datadog.android.trace.internal.domain.event

import com.datadog.android.api.context.DatadogContext
import com.datadog.android.core.internal.utils.toHexString
import com.datadog.android.log.LogAttributes
import com.datadog.android.trace.assertj.SpanEventAssert.Companion.assertThat
import com.datadog.android.utils.forge.Configurator
import com.datadog.opentracing.DDSpan
import com.datadog.tools.unit.setFieldValue
import fr.xgouchet.elmyr.Forge
import fr.xgouchet.elmyr.annotation.BoolForgery
import fr.xgouchet.elmyr.annotation.Forgery
import fr.xgouchet.elmyr.annotation.StringForgery
import fr.xgouchet.elmyr.junit5.ForgeConfiguration
import fr.xgouchet.elmyr.junit5.ForgeExtension
import org.junit.jupiter.api.BeforeEach
Expand Down Expand Up @@ -49,13 +51,13 @@ internal class DdSpanToSpanEventMapperTest {
}

@RepeatedTest(4)
fun `M map a DdSpan to a SpanEvent W map`(
fun `M map a DdSpan to a SpanEvent W map()`(
@Forgery fakeSpan: DDSpan
) {
// WHEN
// When
val event = testedMapper.map(fakeDatadogContext, fakeSpan)

// THEN
// Then
assertThat(event)
.hasSpanId(fakeSpan.spanId.toHexString())
.hasTraceId(fakeSpan.traceId.toHexString())
Expand All @@ -65,6 +67,54 @@ internal class DdSpanToSpanEventMapperTest {
.hasResourceName(fakeSpan.resourceName)
.hasSpanType("custom")
.hasSpanSource(fakeDatadogContext.source)
.hasApplicationId(null)
.hasSessionId(null)
.hasViewId(null)
.hasErrorFlag(fakeSpan.error.toLong())
.hasSpanStartTime(fakeSpan.startTime + fakeDatadogContext.time.serverTimeOffsetNs)
.hasSpanDuration(fakeSpan.durationNano)
.hasTracerVersion(fakeDatadogContext.sdkVersion)
.hasClientPackageVersion(fakeDatadogContext.version)
.apply {
if (fakeNetworkInfoEnabled) {
hasNetworkInfo(fakeDatadogContext.networkInfo)
} else {
doesntHaveNetworkInfo()
}
}
.hasUserInfo(fakeDatadogContext.userInfo)
.hasMeta(fakeSpan.meta)
.hasMetrics(fakeSpan.metrics)
}

@RepeatedTest(4)
fun `M map a DdSpan to a SpanEvent with RUM info W map() {RUM info present}`(
@Forgery fakeSpan: DDSpan,
@StringForgery fakeApplicationId: String,
@StringForgery fakeSessionId: String,
@StringForgery fakeViewId: String
) {
// Given
fakeSpan.setTag(LogAttributes.RUM_APPLICATION_ID, fakeApplicationId)
fakeSpan.setTag(LogAttributes.RUM_SESSION_ID, fakeSessionId)
fakeSpan.setTag(LogAttributes.RUM_VIEW_ID, fakeViewId)

// When
val event = testedMapper.map(fakeDatadogContext, fakeSpan)

// Then
assertThat(event)
.hasSpanId(fakeSpan.spanId.toHexString())
.hasTraceId(fakeSpan.traceId.toHexString())
.hasParentId(fakeSpan.parentId.toHexString())
.hasServiceName(fakeSpan.serviceName)
.hasOperationName(fakeSpan.operationName)
.hasResourceName(fakeSpan.resourceName)
.hasSpanType("custom")
.hasSpanSource(fakeDatadogContext.source)
.hasApplicationId(fakeApplicationId)
.hasSessionId(fakeSessionId)
.hasViewId(fakeViewId)
.hasErrorFlag(fakeSpan.error.toLong())
.hasSpanStartTime(fakeSpan.startTime + fakeDatadogContext.time.serverTimeOffsetNs)
.hasSpanDuration(fakeSpan.durationNano)
Expand All @@ -83,32 +133,32 @@ internal class DdSpanToSpanEventMapperTest {
}

@Test
fun `M mark the SpanEvent as top span W map { parentId is 0 }`(
fun `M mark the SpanEvent as top span W map() { parentId is 0 }`(
@Forgery fakeSpan: DDSpan
) {
// GIVEN
// Given
fakeSpan.setFieldValue("parentId", 0)

// WHEN
// When
val event = testedMapper.map(fakeDatadogContext, fakeSpan)

// THEN
// Then
assertThat(event)
.isTopSpan()
}

@Test
fun `M not mark the SpanEvent as top span W map { parentId is different than 0 }`(
fun `M not mark the SpanEvent as top span W map() { parentId is different than 0 }`(
forge: Forge,
@Forgery fakeSpan: DDSpan
) {
// GIVEN
// Given
fakeSpan.context().setFieldValue("parentId", BigInteger.valueOf(forge.aLong(min = 1)))

// WHEN
// When
val event = testedMapper.map(fakeDatadogContext, fakeSpan)

// THEN
// Then
assertThat(event)
.isNotTopSpan()
}
Expand Down

0 comments on commit b3779e4

Please sign in to comment.