Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
870ed87
APMSVLS-65 first draft of extractor helper function and inclusion in …
rithikanarayan Sep 12, 2025
8a2c8b5
Second draft of implementation for extracting trace context from even…
rithikanarayan Sep 16, 2025
4954749
Merge branch 'main' into rithika.narayan/APMSVLS-65/extract-context-f…
rithikanarayan Sep 19, 2025
ed0b485
Removing unnecessary allocations from header extraction
rithikanarayan Sep 19, 2025
d513e9e
Added unit tests for extracting context from event['request']['headers']
rithikanarayan Sep 22, 2025
8b5ed4e
Refactoring change to use extract_context_from_http_event_or_context
rithikanarayan Sep 23, 2025
d86688b
Removing extra testing file
rithikanarayan Sep 23, 2025
a7aeef1
linting
rithikanarayan Sep 23, 2025
58b3b09
Merge branch 'main' into rithika.narayan/APMSVLS-65/extract-context-f…
rithikanarayan Sep 24, 2025
07ead6d
Cleaned up repeated get calls
rithikanarayan Sep 24, 2025
5d04656
Checking for request header field without raising exception
rithikanarayan Sep 25, 2025
0b6523a
Removing extraneous file
rithikanarayan Sep 25, 2025
804c406
Refactored code, added more unit tests
rithikanarayan Sep 26, 2025
3a08efd
More comprehensive unit testing for coverage
rithikanarayan Sep 26, 2025
794791a
Removing imported files
rithikanarayan Sep 26, 2025
e7c56a4
Removing more unnecessary files
rithikanarayan Sep 26, 2025
09d67d4
WIP testing whether decode_authorizer_context is set
rithikanarayan Sep 29, 2025
cefcd5f
Cleanup
rithikanarayan Sep 29, 2025
76c8bb2
More cleanup
rithikanarayan Sep 29, 2025
b46efbb
Testing refactoring for size
rithikanarayan Sep 29, 2025
4c48de7
Removed comments
rithikanarayan Sep 29, 2025
6bd15cb
removing changes in tracer
rithikanarayan Sep 29, 2025
83f97df
Restoring implementation
rithikanarayan Sep 29, 2025
5a3ad86
Bump zipped layer size
rithikanarayan Sep 29, 2025
937b371
Integer layer size
rithikanarayan Sep 30, 2025
1eec519
Merge branch 'main' into rithika.narayan/APMSVLS-65/extract-context-f…
rithikanarayan Oct 2, 2025
006caee
Fixing layer size calculation
rithikanarayan Oct 2, 2025
7ad64c5
Adding unit test for using extract_context_from_lambda_context
rithikanarayan Oct 7, 2025
c532190
linting
rithikanarayan Oct 7, 2025
fab3c92
Merge branch 'main' into rithika.narayan/APMSVLS-65/extract-context-f…
rithikanarayan Oct 7, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion datadog_lambda/tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,25 @@ def extract_context_from_step_functions(event, lambda_context):
return extract_context_from_lambda_context(lambda_context)


def extract_context_from_request_header(event, lambda_context):
"""
Attempt to extract Datadog trace context from an event payload where Datadog information
is under the event["request"]["header"] section. Intended to replace some of the
need for customers to provide custom extractor functions in their code for workflows such as
RUM -> AppSync -> Lambda.
"""
try:
nested_json = event.get("request").get("headers")
context = propagator.extract(nested_json)

if not _is_context_complete(context):
context = extract_context_from_lambda_context(lambda_context)
except Exception:
context = extract_context_from_lambda_context(lambda_context)

return context


def extract_context_custom_extractor(extractor, event, lambda_context):
"""
Extract Datadog trace context using a custom trace extractor function
Expand Down Expand Up @@ -642,7 +661,7 @@ def extract_dd_trace_context(
elif event_source.equals(EventTypes.STEPFUNCTIONS):
context = extract_context_from_step_functions(event, lambda_context)
else:
context = extract_context_from_lambda_context(lambda_context)
context = extract_context_from_request_header(event, lambda_context)

if _is_context_complete(context):
logger.debug("Extracted Datadog trace context from event or context")
Expand Down
53 changes: 53 additions & 0 deletions tests/event_samples/rum-appsync.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"identity": "None",
"info": {
"fieldName": "getItems",
"parentTypeName": "Query",
"selectionSetGraphQL": "{\n id\n}",
"selectionSetList":["id"]
},
"prev": "None",
"request": {
"domainName": "None",
"headers": {
"accept": "*/*",
"accept-encoding": "gzip, deflate, br, zstd",
"accept-language": "en-US,en;q=0.9",
"cloudfront-forwarded-proto": "https",
"cloudfront-is-desktop-viewer": "True",
"cloudfront-is-mobile-viewer": "False",
"cloudfront-is-smarttv-viewer":"False",
"cloudfront-is-tablet-viewer":" False",
"cloudfront-viewer-asn": "6461",
"cloudfront-viewer-country": "US",
"content-length": "47",
"content-type": "application/graphql",
"host": "4aowrg2uhvbw5mn7osu6searqi.appsync-api.us-east-1.amazonaws.com",
"origin": "http://localhost:5173",
"priority": "u=1, i",
"referer": "http://localhost:5173/",
"sec-ch-ua": "\"Chromium\";v=\"140\", \"Not=A?Brand\";v=\"24\", \"Google Chrome\";v=\"140\"",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "macOS",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "cross-site",
"traceparent": "00-0000000000000000d9f454c80b9a529a-73ac6ca3427073a3-01",
"tracestate": "dd=s:1;o:rum",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","via":"2.0 62f9f3967e93a923f21c8acb20cf10b6.cloudfront.net (CloudFront)",
"x-amz-cf-id": "Femhicb_Vbva-J8qWjdI4hKMmqusCeQSp207UGyY3u8VOUrdE8BBvg==",
"x-amzn-appsync-is-vpce-request": "False",
"x-amzn-remote-ip": "64.124.12.19",
"x-amzn-requestid": "1ee1669a-eda3-4d4f-911c-35f74ebef31d",
"x-amzn-trace-id": "Root=1-68cdb7e9-438bf88259d7ce3535723bdd",
"x-datadog-origin": "rum",
"x-datadog-parent-id": "67890",
"x-datadog-sampling-priority": "1",
"x-datadog-trace-id": "12345",
"x-forwarded-for": "64.124.12.19,15.158.225.229",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
}
},
"source": "None"
}
79 changes: 79 additions & 0 deletions tests/test_tracing.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ def _wrap(*args, **kwargs):
),
),
("lambda-url", None),
(
"rum-appsync",
Context(
trace_id=12345,
span_id=67890,
sampling_priority=1,
)
),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lot more testing that we're going to need. When thinking about test coverage, I think about two things.

  1. Coverage. If I were to run a coverage report on our tests, would I see that we've hit every line of code? In the current case, the answer is no.

  2. Logic. If I were to make a change to any line of your code, would a test fail? For example, if I change a in to not in, I would expect to see a failing test. In the current case, this could mean testing that request is a dict but headers is not in it and vice versa.

We also would need a test that makes sure that the authorizer context is never decoded.

("s3", None),
(
"sns-b64-msg-attribute",
Expand Down Expand Up @@ -526,6 +534,77 @@ def test_with_sqs_distributed_w3c_trace_data(self):
}
self.common_tests_with_trace_context_extraction_injection(headers, sqs_event)

@with_trace_propagation_style("datadog")
def test_with_request_header_datadog_trace_data(self):
"""Test trace data extraction from event['request']['headers']"""
headers = {
TraceHeader.TRACE_ID: "12345",
TraceHeader.PARENT_ID: "67890",
TraceHeader.SAMPLING_PRIORITY: "1",
}
request_headers = {
"request": {
"domainName": "None",
"headers": {
"content-length": "47",
"content-type": "application/graphql",
"host": "4aowrg2uhvbw5mn7osu6searqi.appsync-api.us-east-1.amazonaws.com",
"origin": "http://localhost:5173",
"priority": "u=1, i",
"referer": "http://localhost:5173/",
"traceparent": "00-0000000000000000d9f454c80b9a529a-73ac6ca3427073a3-01",
"tracestate": "dd=s:1;o:rum",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","via":"2.0 62f9f3967e93a923f21c8acb20cf10b6.cloudfront.net (CloudFront)",
"x-amz-cf-id": "Femhicb_Vbva-J8qWjdI4hKMmqusCeQSp207UGyY3u8VOUrdE8BBvg==",
"x-amzn-appsync-is-vpce-request": "False",
"x-amzn-remote-ip": "64.124.12.19",
"x-amzn-requestid": "1ee1669a-eda3-4d4f-911c-35f74ebef31d",
"x-amzn-trace-id": "Root=1-68cdb7e9-438bf88259d7ce3535723bdd",
"x-datadog-parent-id": "67890",
"x-datadog-sampling-priority": "1",
"x-datadog-trace-id": "12345",
"x-forwarded-for": "64.124.12.19,15.158.225.229",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
}
},
}
self.common_tests_with_trace_context_extraction_injection(headers, request_headers)

@with_trace_propagation_style("tracecontext")
def test_with_request_header_w3_trace_data(self):
"""Test trace data extraction from event['request']['headers']"""
headers = {
"traceparent": "00-0000000000000000d9f454c80b9a529a-73ac6ca3427073a3-01",
"tracestate": "dd=s:1;o:rum",
}
request_headers = {
"request": {
"domainName": "None",
"headers": {
"content-length": "47",
"content-type": "application/graphql",
"host": "4aowrg2uhvbw5mn7osu6searqi.appsync-api.us-east-1.amazonaws.com",
"origin": "http://localhost:5173",
"priority": "u=1, i",
"referer": "http://localhost:5173/",
"traceparent": "00-0000000000000000d9f454c80b9a529a-73ac6ca3427073a3-01",
"tracestate": "dd=s:1;o:rum",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36","via":"2.0 62f9f3967e93a923f21c8acb20cf10b6.cloudfront.net (CloudFront)",
"x-amz-cf-id": "Femhicb_Vbva-J8qWjdI4hKMmqusCeQSp207UGyY3u8VOUrdE8BBvg==",
"x-amzn-appsync-is-vpce-request": "False",
"x-amzn-remote-ip": "64.124.12.19",
"x-amzn-requestid": "1ee1669a-eda3-4d4f-911c-35f74ebef31d",
"x-amzn-trace-id": "Root=1-68cdb7e9-438bf88259d7ce3535723bdd",
"x-forwarded-for": "64.124.12.19,15.158.225.229",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
}
},
}
self.common_tests_with_trace_context_extraction_injection(headers, request_headers)


@with_trace_propagation_style("datadog")
def test_with_legacy_client_context_datadog_trace_data(self):
headers = {
Expand Down
Loading