Skip to content

Commit 76df05c

Browse files
Fixed issue with spanId and parentId that should be serialized as unsigned long.
1 parent 6f80b05 commit 76df05c

File tree

2 files changed

+92
-5
lines changed

2 files changed

+92
-5
lines changed

dd-trace-core/src/main/java/datadog/trace/common/writer/ddagent/TraceMapperV1.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,9 @@ private void encodeSpans(
149149
// sometimes called endpoint for web spans
150150
encodeField(writable, 3, span.getResourceName());
151151
// spanID = 4, the ID of this span
152-
encodeField(writable, 4, span.getSpanId());
152+
encodeUnsignedField(writable, 4, span.getSpanId());
153153
// parentID = 5, the ID of this span's parent, or zero if there is no parent
154-
encodeField(writable, 5, span.getParentId());
154+
encodeUnsignedField(writable, 5, span.getParentId());
155155
// start = 6, the number of nanoseconds from the Unix epoch to the start of this span
156156
encodeField(writable, 6, span.getStartTime());
157157
// duration = 7, the time length of this span in nanoseconds
@@ -189,7 +189,7 @@ private void encodeSpanLinks(Writable writable, int fieldId, List<AgentSpanLink>
189189
for (AgentSpanLink link : links) {
190190
writable.startMap(5);
191191
encodeField(writable, 1, link.traceId().to128BitBytes());
192-
encodeField(writable, 2, link.spanId());
192+
encodeUnsignedField(writable, 2, link.spanId());
193193
Map<String, Object> attributes = new LinkedHashMap<>();
194194
attributes.putAll(link.attributes().asMap());
195195
encodeAttributes(writable, 3, attributes, emptyMap());
@@ -489,6 +489,11 @@ private void encodeField(Writable writable, int fieldId, long value) {
489489
writable.writeLong(value);
490490
}
491491

492+
private void encodeUnsignedField(Writable writable, int fieldId, long value) {
493+
writable.writeInt(fieldId);
494+
writable.writeUnsignedLong(value);
495+
}
496+
492497
private void encodeField(Writable writable, int fieldId, CharSequence value) {
493498
writable.writeInt(fieldId);
494499
writeStreamingString(writable, value);

dd-trace-core/src/test/groovy/datadog/trace/common/writer/ddagent/TraceMapperV1PayloadTest.groovy

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,80 @@ class TraceMapperV1PayloadTest extends DDSpecification {
229229
"invalid" | SamplingMechanism.DEFAULT
230230
}
231231

232+
def "test span ids are encoded as unsigned values in v1 payloads"() {
233+
setup:
234+
long spanId = Long.MIN_VALUE + 123L
235+
long parentId = Long.MIN_VALUE + 456L
236+
def span = new TraceGenerator.PojoSpan(
237+
"service-a",
238+
"operation-a",
239+
"resource-a",
240+
DDTraceId.ONE,
241+
spanId,
242+
parentId,
243+
1000L,
244+
2000L,
245+
0,
246+
[:],
247+
[:],
248+
"web",
249+
false,
250+
PrioritySampling.SAMPLER_KEEP,
251+
200,
252+
null)
253+
254+
TraceMapperV1 mapper = new TraceMapperV1()
255+
byte[] encoded = serializeMappedPayload(mapper, [[span]])
256+
MessageUnpacker unpacker = MessagePack.newDefaultUnpacker(encoded)
257+
List<String> stringTable = new ArrayList<>()
258+
stringTable.add("")
259+
260+
when:
261+
unpacker.unpackMapHeader()
262+
Long actualSpanId = null
263+
Long actualParentId = null
264+
265+
for (int i = 0; i < 10; i++) {
266+
int payloadFieldId = unpacker.unpackInt()
267+
if (payloadFieldId == 11) {
268+
int chunkCount = unpacker.unpackArrayHeader()
269+
assertEquals(1, chunkCount)
270+
int chunkFieldCount = unpacker.unpackMapHeader()
271+
for (int j = 0; j < chunkFieldCount; j++) {
272+
int chunkFieldId = unpacker.unpackInt()
273+
if (chunkFieldId == 4) {
274+
int spanCount = unpacker.unpackArrayHeader()
275+
assertEquals(1, spanCount)
276+
int spanFieldCount = unpacker.unpackMapHeader()
277+
for (int k = 0; k < spanFieldCount; k++) {
278+
int spanFieldId = unpacker.unpackInt()
279+
switch (spanFieldId) {
280+
case 4:
281+
assertEquals(MessageFormat.UINT64, unpacker.nextFormat)
282+
actualSpanId = DDSpanId.from("${unpacker.unpackBigInteger()}")
283+
break
284+
case 5:
285+
assertEquals(MessageFormat.UINT64, unpacker.nextFormat)
286+
actualParentId = DDSpanId.from("${unpacker.unpackBigInteger()}")
287+
break
288+
default:
289+
skipSpanField(unpacker, spanFieldId, stringTable)
290+
}
291+
}
292+
} else {
293+
skipChunkField(unpacker, chunkFieldId, stringTable)
294+
}
295+
}
296+
} else {
297+
skipPayloadField(unpacker, payloadFieldId, stringTable)
298+
}
299+
}
300+
301+
then:
302+
assertEquals(spanId, actualSpanId)
303+
assertEquals(parentId, actualParentId)
304+
}
305+
232306
def "test span links are encoded from structured span links"() {
233307
setup:
234308
List<SpanLink> spanLinks = [
@@ -783,10 +857,10 @@ class TraceMapperV1PayloadTest extends DDSpecification {
783857
resource = readStreamingString(unpacker, stringTable)
784858
break
785859
case 4:
786-
spanId = unpacker.unpackValue().asNumberValue().toLong()
860+
spanId = unpackUnsignedLong(unpacker)
787861
break
788862
case 5:
789-
parentId = unpacker.unpackValue().asNumberValue().toLong()
863+
parentId = unpackUnsignedLong(unpacker)
790864
break
791865
case 6:
792866
start = unpacker.unpackLong()
@@ -919,6 +993,14 @@ class TraceMapperV1PayloadTest extends DDSpecification {
919993
}
920994
}
921995

996+
private static long unpackUnsignedLong(MessageUnpacker unpacker) {
997+
MessageFormat format = unpacker.nextFormat
998+
if (format == MessageFormat.UINT64) {
999+
return DDSpanId.from("${unpacker.unpackBigInteger()}")
1000+
}
1001+
return unpacker.unpackLong()
1002+
}
1003+
9221004
private static void addFlattenedExpectedAttribute(
9231005
Map<String, Object> expectedAttributes,
9241006
String key,

0 commit comments

Comments
 (0)