-
Notifications
You must be signed in to change notification settings - Fork 45
Explicit trace ID propagation for SFN #526
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
Changes from 14 commits
7c127a3
8658dea
3eccb20
97b189a
eaa09f3
2baec69
3c4014b
6f54a00
4e0afdb
25780a8
85a157f
aad3cd8
c3681de
7d1d475
e9a7d46
a6464b4
068c2fc
6105b21
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ | |
TraceContextSource, | ||
XrayDaemon, | ||
Headers, | ||
TraceHeader, | ||
) | ||
from datadog_lambda.xray import ( | ||
send_segment, | ||
|
@@ -357,8 +358,10 @@ def extract_context_from_kinesis_event(event, lambda_context): | |
|
||
|
||
def _deterministic_sha256_hash(s: str, part: str) -> (int, int): | ||
sha256_hash = hashlib.sha256(s.encode()).hexdigest() | ||
return _sha256_to_binary_part(hashlib.sha256(s.encode()).hexdigest(), part) | ||
|
||
|
||
def _sha256_to_binary_part(sha256_hash: str, part: str) -> (int, int): | ||
# First two chars is '0b'. zfill to ensure 256 bits, but we only care about the first 128 bits | ||
binary_hash = bin(int(sha256_hash, 16))[2:].zfill(256) | ||
if part == HIGHER_64_BITS: | ||
|
@@ -377,30 +380,53 @@ def extract_context_from_step_functions(event, lambda_context): | |
into lambda's event dict. | ||
""" | ||
try: | ||
execution_id = event.get("Execution").get("Id") | ||
state_name = event.get("State").get("Name") | ||
state_entered_time = event.get("State").get("EnteredTime") | ||
# returning 128 bits since 128bit traceId will be break up into | ||
# traditional traceId and _dd.p.tid tag | ||
# https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 | ||
trace_id = _deterministic_sha256_hash(execution_id, LOWER_64_BITS) | ||
|
||
parent_id = _deterministic_sha256_hash( | ||
f"{execution_id}#{state_name}#{state_entered_time}", HIGHER_64_BITS | ||
) | ||
meta = {} | ||
|
||
if "_datadog" in event: | ||
dd_data = event.get("_datadog") | ||
parent_id = _sha256_to_binary_part( | ||
dd_data.get("x-datadog-parent-id-hash"), HIGHER_64_BITS | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: Since this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might be misunderstanding, we're not checking if the hash key exists right? We're computing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So we're saying it's the same If we want to separate them, one thing we could do is make a new V2 event with a V2 extractor to go along with it |
||
) | ||
if "x-datadog-trace-id" in dd_data: # lambda root | ||
dd_data["x-datadog-parent-id"] = str(parent_id) | ||
explicit_context = propagator.extract(dd_data) | ||
if _is_context_complete(explicit_context): | ||
return explicit_context | ||
else: | ||
return None | ||
else: # sfn root | ||
trace_id = _sha256_to_binary_part( | ||
dd_data.get("x-datadog-trace-id-hash"), LOWER_64_BITS | ||
) | ||
meta["_dd.p.tid"] = hex( | ||
_sha256_to_binary_part( | ||
dd_data.get("x-datadog-trace-id-hash"), HIGHER_64_BITS | ||
) | ||
)[2:] | ||
Comment on lines
+392
to
+400
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
else: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This whole branch should be the old behavior |
||
execution_id = event.get("Execution").get("Id") | ||
state_name = event.get("State").get("Name") | ||
state_entered_time = event.get("State").get("EnteredTime") | ||
# returning 128 bits since 128bit traceId will be break up into | ||
# traditional traceId and _dd.p.tid tag | ||
# https://github.com/DataDog/dd-trace-py/blob/3e34d21cb9b5e1916e549047158cb119317b96ab/ddtrace/propagation/http.py#L232-L240 | ||
trace_id = _deterministic_sha256_hash(execution_id, LOWER_64_BITS) | ||
# take the higher 64 bits as _dd.p.tid tag and use hex to encode | ||
# [2:] to remove '0x' in the hex str | ||
meta["_dd.p.tid"] = hex( | ||
_deterministic_sha256_hash(execution_id, HIGHER_64_BITS) | ||
)[2:] | ||
|
||
parent_id = _deterministic_sha256_hash( | ||
f"{execution_id}#{state_name}#{state_entered_time}", HIGHER_64_BITS | ||
) | ||
|
||
sampling_priority = SamplingPriority.AUTO_KEEP | ||
return Context( | ||
trace_id=trace_id, | ||
span_id=parent_id, | ||
sampling_priority=sampling_priority, | ||
# take the higher 64 bits as _dd.p.tid tag and use hex to encode | ||
# [2:] to remove '0x' in the hex str | ||
meta={ | ||
"_dd.p.tid": hex( | ||
_deterministic_sha256_hash(execution_id, HIGHER_64_BITS) | ||
)[2:] | ||
}, | ||
meta=meta, | ||
) | ||
except Exception as e: | ||
logger.debug("The Step Functions trace extractor returned with error %s", e) | ||
|
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.
Split this up with a helper so we have an entrypoint for our
sha256_hash
from thex-datadog-trace-id-hash
andx-datadog-parent-id-hash
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.
nice!