Skip to content

Commit 4b141c0

Browse files
authored
fix(tracing): ensure 128 trace ids are propagated by datadog headers [backports #5510 to 1.11] (#5514)
Backport: #5510 ## Checklist - [x] Change(s) are motivated and described in the PR description. - [x] Testing strategy is described if automated tests are not included in the PR. - [x] Risk is outlined (performance impact, potential for breakage, maintainability, etc). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] [Library release note guidelines](https://ddtrace.readthedocs.io/en/stable/contributing.html#Release-Note-Guidelines) are followed. - [x] Documentation is included (in-code, generated user docs, [public corp docs](https://github.com/DataDog/documentation/)). - [x] PR description includes explicit acknowledgement/acceptance of the performance implications of this PR as reported in the benchmarks PR comment. ## Reviewer Checklist - [x] Title is accurate. - [x] No unnecessary changes are introduced. - [x] Description motivates each change. - [x] Avoids breaking [API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces) changes unless absolutely necessary. - [x] Testing strategy adequately addresses listed risk(s). - [x] Change is maintainable (easy to change, telemetry, documentation). - [x] Release note makes sense to a user of the library. - [x] Reviewer has explicitly acknowledged and discussed the performance implications of this PR as reported in the benchmarks PR comment.
1 parent 82e7c31 commit 4b141c0

File tree

3 files changed

+27
-32
lines changed

3 files changed

+27
-32
lines changed

ddtrace/propagation/http.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -266,19 +266,21 @@ def _extract(headers):
266266
}
267267
log.debug("failed to decode x-datadog-tags: %r", tags_value, exc_info=True)
268268

269-
if meta is not None and config._128_bit_trace_id_enabled:
270-
# When 128 bit trace ids are propagated the 64 lowest order bits are encoded as an integer
271-
# and set in the `x-datadog-trace-id` header (this was done for backwards compatibility).
272-
# The 64 highest order bits are encoded in base 16 and store in the `_dd.p.tid` tag.
269+
if meta and _HIGHER_ORDER_TRACE_ID_BITS in meta:
270+
# When 128 bit trace ids are propagated the 64 lowest order bits are set in the `x-datadog-trace-id`
271+
# header. The 64 highest order bits are encoded in base 16 and store in the `_dd.p.tid` tag.
273272
# Here we reconstruct the full 128 bit trace_id.
274-
trace_id_hob_hex = meta.get(_HIGHER_ORDER_TRACE_ID_BITS) # type: Optional[str]
275-
if trace_id_hob_hex is not None:
276-
# convert lowest order bits in trace_id to base 16
277-
trace_id_lod_hex = "{:016x}".format(trace_id)
273+
trace_id_hob_hex = meta[_HIGHER_ORDER_TRACE_ID_BITS]
274+
try:
275+
if len(trace_id_hob_hex) != 16:
276+
raise ValueError("Invalid size")
278277
# combine highest and lowest order hex values to create a 128 bit trace_id
279-
trace_id = int(trace_id_hob_hex + trace_id_lod_hex, 16)
280-
# After the full trace id is reconstructed this tag is no longer required
281-
del meta[_HIGHER_ORDER_TRACE_ID_BITS]
278+
trace_id = int(trace_id_hob_hex + "{:016x}".format(trace_id), 16)
279+
except ValueError:
280+
meta["_dd.propagation_error"] = "malformed_tid {}".format(trace_id_hob_hex)
281+
log.warning("malformed_tid: %s. Failed to decode trace id from http headers", trace_id_hob_hex)
282+
# After the full trace id is reconstructed this tag is no longer required
283+
del meta[_HIGHER_ORDER_TRACE_ID_BITS]
282284

283285
# Try to parse values into their expected types
284286
try:
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
fixes:
3+
- |
4+
tracing: Ensure datadog headers propagate 128 bit trace ids when ``DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED=False``

tests/tracer/test_propagation.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -217,28 +217,17 @@ def test_extract(tracer):
217217
}
218218

219219

220-
@pytest.mark.subprocess(
221-
env=dict(DD_TRACE_128_BIT_TRACEID_GENERATION_ENABLED="true"),
222-
parametrize={
223-
"TEST_TRACE_ID": [
224-
str(2 ** 128 - 1),
225-
str(2 ** 127 + 1),
226-
str(2 ** 65 - 1),
227-
str(2 ** 64 + 1),
228-
str(2 ** 127 + 2 ** 63),
229-
]
230-
},
220+
@pytest.mark.parametrize(
221+
"trace_id",
222+
[
223+
2 ** 128 - 1,
224+
2 ** 127 + 1,
225+
2 ** 65 - 1,
226+
2 ** 64 + 1,
227+
2 ** 127 + 2 ** 63,
228+
],
231229
)
232-
def test_extract_128bit_trace_ids():
233-
import os
234-
235-
from ddtrace.internal.constants import HIGHER_ORDER_TRACE_ID_BITS
236-
from ddtrace.propagation.http import HTTPPropagator
237-
from tests.utils import DummyTracer
238-
239-
tracer = DummyTracer()
240-
241-
trace_id = int(os.getenv("TEST_TRACE_ID"))
230+
def test_extract_128bit_trace_ids(tracer, trace_id):
242231
trace_id_64bit = trace_id & 2 ** 64 - 1
243232
# Get the hex representation of the 64 most signicant bits
244233
trace_id_hob_hex = "{:032x}".format(trace_id)[:16]

0 commit comments

Comments
 (0)