-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RUM-4116 Add the SpanLink support for Otel API implementation #1993
RUM-4116 Add the SpanLink support for Otel API implementation #1993
Conversation
799a676
to
89ec036
Compare
...c/main/kotlin/com/datadog/android/trace/internal/domain/event/OtelDdSpanToSpanEventMapper.kt
Outdated
Show resolved
Hide resolved
89ec036
to
fec3fba
Compare
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## feature/otel-support #1993 +/- ##
========================================================
+ Coverage 60.26% 60.29% +0.04%
========================================================
Files 808 808
Lines 30184 30196 +12
Branches 4945 4950 +5
========================================================
+ Hits 18188 18206 +18
- Misses 10772 10775 +3
+ Partials 1224 1215 -9
|
private fun Forge.exhaustiveAttributes(): Map<String, String> { | ||
return listOf( | ||
aString() | ||
).map { anAlphabeticalString() to it } | ||
.toMap(mutableMapOf()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to redefine it, you should be able to import one defined in tools:unit
module (com.datadog.tools.unit.forge
package). Anyway, in this particular case it is not exhaustive attributes
, because it is always String
to String
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes that is the reason why I did not import it but you are right I need to change that name
@@ -35,6 +36,8 @@ internal class CoreDDSpanForgeryFactory : ForgeryFactory<DDSpan> { | |||
whenever(it.baggageItems).thenReturn(baggageItems) | |||
whenever(it.tags).thenReturn(tagsAndMetrics) | |||
} | |||
val spanLinks = forge.aList(size = forge.anInt(min = 0, max = 10)) { forge.getForgery<AgentSpanLink>() } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
val spanLinks = forge.aList(size = forge.anInt(min = 0, max = 10)) { forge.getForgery<AgentSpanLink>() } | |
val spanLinks = forge.aList(size = forge.anInt(min = 0, max = 10)) { getForgery<AgentSpanLink>() } |
// endregion | ||
|
||
companion object { | ||
internal const val RUM_ENDPOINT_REQUIRED_TRACE_ID_LENGTH = 16 | ||
private const val LESS_SIGNIFICANT_64_BITS_AS_HEXA_LENGTH = 16 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably need to use word hex
instead of hexa
. The only usages of hexa
I find is for color (which makes sense because it is RGB as hex + alpha as hex). Same applies for other mentions of hexa
in this PR.
Also it should be least
, not less
for LSB (least significant bits).
private const val LESS_SIGNIFICANT_64_BITS_AS_HEXA_LENGTH = 16 | |
private const val LEAST_SIGNIFICANT_64_BITS_AS_HEX_LENGTH = 16 |
return model.traceId.toHexString().takeLast(RUM_ENDPOINT_REQUIRED_TRACE_ID_LENGTH) | ||
// because the backend endpoint does not support 32 hexa characters trace ids we are going to take only the | ||
// less significant 64 bits of the trace id. Later on when we will introduce the 128 bits support | ||
// the more significant bits will be reported in a separated dedicated meta tag. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// the more significant bits will be reported in a separated dedicated meta tag. | |
// the most significant bits will be reported in a separated dedicated meta tag. |
@@ -90,7 +104,10 @@ internal class OtelDdSpanToSpanEventMapper( | |||
view = event.tags[LogAttributes.RUM_VIEW_ID]?.let { SpanEvent.View(it as? String) } | |||
) | |||
val tags = event.tags.mapValues { it.value.toString() } | |||
val meta = (event.baggage + tags).toMutableMap() | |||
val meta: MutableMap<String, String> = mutableMapOf() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor suggestion
val meta: MutableMap<String, String> = mutableMapOf() | |
val meta = mutableMapOf<String, String>() |
} | ||
|
||
private fun resolveSpanLink(link: AgentSpanLink): JsonObject { | ||
// The SpanLinks support the full 128 bits trace so we can use the full hexa string |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// The SpanLinks support the full 128 bits trace so we can use the full hexa string | |
// The SpanLinks support the full 128 bits trace so we can use the full hex string |
val actualLink = deserializedLinks[index].asJsonObject | ||
val actualTraceId = actualLink.get("trace_id").asString | ||
val traceId = link.traceId().toHexString() | ||
assertThat(actualTraceId) | ||
.overridingErrorMessage( | ||
"Expected SpanEvent to have span link trace id: " + | ||
"$traceId but " + | ||
"instead was: $actualTraceId" | ||
) | ||
.isEqualTo(traceId) | ||
val actualSpanId = actualLink.get("span_id").asString | ||
val spanId = DDSpanId.toHexStringPadded(link.spanId()) | ||
assertThat(actualSpanId) | ||
.overridingErrorMessage( | ||
"Expected SpanEvent to have span link span id: " + | ||
"$spanId but " + | ||
"instead was: $$actualSpanId" | ||
) | ||
.isEqualTo(spanId) | ||
val traceFlags = link.traceFlags() | ||
if (traceFlags.toInt() != 0) { | ||
val actualTraceFlags = actualLink.get("flags").asByte | ||
assertThat(actualTraceFlags) | ||
.overridingErrorMessage( | ||
"Expected SpanEvent to have span link flags: " + | ||
"$traceFlags but " + | ||
"instead was: $actualTraceFlags" | ||
) | ||
.isEqualTo(traceFlags) | ||
} else { | ||
assertThat(actualLink.has("flags")) | ||
.overridingErrorMessage( | ||
"Expected SpanEvent to not have span link flags but " + | ||
"instead was: $actualLink" | ||
) | ||
.isFalse() | ||
} | ||
val actualTraceState = actualLink.get("tracestate").asString | ||
if (actualTraceState.isNotEmpty()) { | ||
val traceState = link.traceState() | ||
assertThat(actualTraceState) | ||
.overridingErrorMessage( | ||
"Expected SpanEvent to have span link trace state: " + | ||
"$traceState but " + | ||
"instead was: $actualTraceState" | ||
) | ||
.isEqualTo(traceState) | ||
} else { | ||
assertThat(actualLink.has("tracestate")) | ||
.overridingErrorMessage( | ||
"Expected SpanEvent to not have span link trace state but " + | ||
"instead was: $actualLink" | ||
) | ||
.isFalse() | ||
} | ||
val actualAttributes = actualLink.get("attributes").toString() | ||
val expectedAttributes = link.attributes().asMap() | ||
val jsonObject = JsonObject() | ||
expectedAttributes.forEach { (key, value) -> | ||
jsonObject.addProperty(key, value) | ||
} | ||
val expectedAttributesJsonString = jsonObject.toString() | ||
assertThat(actualAttributes) | ||
.overridingErrorMessage( | ||
"Expected SpanEvent to have span link attributes: " + | ||
"$expectedAttributesJsonString but " + | ||
"instead was: $actualAttributes" | ||
) | ||
.isEqualTo(expectedAttributesJsonString) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not blocking: maybe extract this into a dedicated assert / split assertions? a bit hard to read
fec3fba
to
94ba118
Compare
cd0841b
to
40ec44a
Compare
detekt_custom.yml
Outdated
@@ -1120,6 +1120,7 @@ datadog: | |||
- "kotlin.String.substringAfter(kotlin.Char, kotlin.String)" | |||
- "kotlin.String.substringAfterLast(kotlin.Char, kotlin.String)" | |||
- "kotlin.String.substringBefore(kotlin.Char, kotlin.String)" | |||
- "kotlin.String.takeLessSignificant64Bits()" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- "kotlin.String.takeLessSignificant64Bits()" | |
- "kotlin.String.takeLeastSignificant64Bits()" |
40ec44a
to
f28a8cf
Compare
What does this PR do?
The Otel
SpanBuilder#addLink
API delegates to theDDSpan
under the hood and adds anAgentSpanLink
to it.In this PR we are adding the links support into our
OtelDdSpanToSpanEventMapper
by serializing theAgentSpanLink
list and adding it as aString/String
entry into theSpanEvent.meta
map.Example of a serialized span link into the
meta
section:Motivation
What inspired you to submit this pull request?
Additional Notes
Anything else we should know when reviewing?
Review checklist (to be filled by reviewers)