Uh oh!
There was an error while loading. Please reload this page.
fix: honor upstream trace context in Step Functions Execution.Input._datadog (APMSVLS-513) - #830
Conversation
…datadog Legacy Step Functions invocations were ignoring upstream Datadog trace headers nested under Execution.Input._datadog and always hashing Execution.Id instead. Extract shared helper and read _datadog before falling back to deterministic trace id generation. APMSVLS-513 Co-authored-by: Cursor <cursoragent@cursor.com>
|
There was a problem hiding this comment.
Pull request overview
This PR updates Step Functions trace context extraction to prefer upstream Datadog trace headers found in Execution.Input._datadog (legacy JSONPath-style), and refactors shared parsing logic into a helper to reuse across extraction paths.
Changes:
- Add
_extract_dd_trace_id_from_dd_datahelper to parsex-datadog-trace-idand optional_dd.p.tidfromx-datadog-tags. - Update Step Functions extraction to read upstream trace context from
Execution.Input._datadogbefore falling back to deterministic hashing ofExecution.Id. - Add unit tests covering
_datadogpresent (with/without_dd.p.tid) and absent fallback behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
datadog_lambda/tracing.py | Adds a helper for extracting Datadog trace id / tid and updates Step Functions extraction precedence to honor upstream context in Execution.Input._datadog. |
tests/test_tracing.py | Adds tests for legacy Step Functions events with Execution.Input._datadog and ensures correct fallback when absent. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| execution = event.get("Execution", {}) | ||
| dd_input = execution.get("Input", {}).get("_datadog") | ||
| trace_id = _extract_dd_trace_id_from_dd_data(dd_input, meta) |
There was a problem hiding this comment.
Same here, should be fine
| def _extract_dd_trace_id_from_dd_data(dd_data, meta): | ||
| """ | ||
| Read native Datadog trace headers from a `_datadog` dict. | ||
| Returns the 64-bit trace_id and populates meta["_dd.p.tid"] when present. | ||
| Returns None if no usable trace id is found. | ||
| """ | ||
| if not dd_data or "x-datadog-trace-id" not in dd_data: | ||
| return None | ||
| trace_id = int(dd_data.get("x-datadog-trace-id")) | ||
| high_64_bit_trace_id = _parse_high_64_bits(dd_data.get("x-datadog-tags")) | ||
| if high_64_bit_trace_id: | ||
| meta["_dd.p.tid"] = high_64_bit_trace_id | ||
| return trace_id |
There was a problem hiding this comment.
I think this is fine. You're reusing the existing code so should be ok
Uh oh!
There was an error while loading. Please reload this page.
Summary
Execution.Input._datadogbefore falling back to hashingExecution.Id_extract_dd_trace_id_from_dd_datahelper and reuse it for the v1 lambda-root path_datadogpresent (with/without_dd.p.tid) and absent fallback behaviorJira: APMSVLS-513
Test plan
pytest tests/test_tracing.py::TestExtractAndGetDDTraceContext::test_step_function_trace_data_with_input_datadogpytest tests/test_tracing.py::TestExtractAndGetDDTraceContext::test_step_function_trace_data_input_datadog_without_tidpytest tests/test_tracing.py::TestExtractAndGetDDTraceContext::test_step_function_trace_data_input_without_datadogtests/test_tracing.pysuite in CITest Traces
Pre-fix (not connected):
https://ddserverless.datadoghq.com/apm/trace/141128433036377877332057539723763765387 -- upstream
https://ddserverless.datadoghq.com/apm/trace/173847457712912341096140011075384478337 -- downstream
Post-fix (connected, downstream lambda has an upstream parent):
https://ddserverless.datadoghq.com/apm/trace/141128412120142973548948775510277637565
Made with Cursor