Skip to content

Conversation

@Dogbu-cyber
Copy link

@Dogbu-cyber Dogbu-cyber commented Jan 28, 2026

APMSVLS-197 feat: Add check to extract trace context from event.request.headers

Overview

This PR adds automatic trace context extraction from event.request.headers for AppSync integration scenarios. This eliminates the need for customers to use customized extractors for RUM → AppSync → Lambda resolver flows where RUM-injected trace context is nested under event["request"]["headers"].

Problem

Previously, trace context from RUM was not propagated through AppSync to Lambda resolvers because the extension only checked:

  1. Trigger-specific headers (via span inferrer)
  2. event.headers (top-level event headers)
  3. Request headers (HTTP request headers)

For AppSync, the trace context is nested under event.request.headers, which was not checked, causing traces to break at the AppSync boundary.

Solution

Added a step that checks event.request.headers after all other trace context sources have been attempted.

Trace Examples

Before

Without this change, trace context is lost at the AppSync boundary:

Trace showing broken propagation through AppSync

Log showing the passed header value for x-datadog-trace-id does not align with the given trace_id

Flow: RUM → AppSync → Lambda (trace ID not propagated)

After

With this change, trace context is properly extracted and propagated:

Trace showing successful propagation through AppSync

Flow: RUM → AppSync → Lambda resolver (trace continues using value within x-datadog-trace-id)

Testing

Unit Tests

Added 10 unit tests covering:

  • Extraction from event.request.headers with Datadog headers
  • Extraction from event.request.headers with W3C TraceContext headers
  • Edge cases (missing headers, empty objects, invalid data)

Run tests with:

cargo test test_extract_span_context -- --nocapture

@Dogbu-cyber Dogbu-cyber changed the title David.ogbureke/extract tracecontext appsync https://datadoghq.atlassian.net/browse/APMSVLS-197 [APMSVLS-197] Add fallback to extract trace context from event.request.headers Jan 28, 2026
@Dogbu-cyber Dogbu-cyber reopened this Jan 28, 2026
@Dogbu-cyber Dogbu-cyber requested a review from Copilot January 28, 2026 18:51
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a fallback mechanism to extract distributed tracing context from event.request.headers for AppSync integration scenarios. This enhancement eliminates the need for custom extractors when RUM injects trace context into AppSync → Lambda resolver flows.

Changes:

  • Added nested extraction logic to check event.request.headers after primary headers extraction fails

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Dogbu-cyber Dogbu-cyber marked this pull request as draft January 28, 2026 18:54
@Dogbu-cyber Dogbu-cyber force-pushed the david.ogbureke/extract-tracecontext-appsync branch from f267045 to 5e936c4 Compare January 28, 2026 18:56
@Dogbu-cyber Dogbu-cyber marked this pull request as ready for review January 28, 2026 20:31
@Dogbu-cyber Dogbu-cyber marked this pull request as draft January 28, 2026 20:46
@Dogbu-cyber Dogbu-cyber force-pushed the david.ogbureke/extract-tracecontext-appsync branch from 5e936c4 to e4d03a2 Compare January 28, 2026 20:47
…request.headers

Add automatic trace context extraction from event.request.headers for
AppSync integration scenarios. This eliminates the need for customers
to use customized extractors for RUM → AppSync → Lambda resolver flows
where RUM-injected trace context is nested under event["request"]["headers"].
@Dogbu-cyber Dogbu-cyber force-pushed the david.ogbureke/extract-tracecontext-appsync branch 2 times, most recently from 4043feb to 8a2baca Compare January 28, 2026 20:54
@Dogbu-cyber Dogbu-cyber marked this pull request as ready for review January 28, 2026 20:59
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add some unit testing and show an example trace in the PR description? Just to see what were we missing

@Dogbu-cyber Dogbu-cyber force-pushed the david.ogbureke/extract-tracecontext-appsync branch from 96d4cb4 to b0619c2 Compare January 29, 2026 17:54
@duncanista duncanista requested a review from Copilot January 29, 2026 18:48
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Dogbu-cyber Dogbu-cyber force-pushed the david.ogbureke/extract-tracecontext-appsync branch from b0619c2 to 391f38c Compare January 29, 2026 18:50
Comment on lines 1075 to 1085
}

if let Some(request_obj) = payload_value.get("request") {
if let Some(request_headers) = request_obj.get("headers") {
if let Some(sc) = propagator.extract(request_headers) {
debug!("Extracted trace context from event.request.headers");
return Some(sc);
}
}
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Why did you decided that this should be last priority?

Copy link
Author

Choose a reason for hiding this comment

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

I assumed there was some reason for the original order, so I didn't take a stance on where exactly it should go and added it as the last case..

Copy link
Contributor

Choose a reason for hiding this comment

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

Based on other projects which support AppSync extraction, it seems that they are considered in the same order as inferred spans would do it – I'd suggest to follow that same order

https://github.com/DataDog/datadog-lambda-js/blob/main/src/trace/context/extractor.ts#L92

Copy link
Author

Choose a reason for hiding this comment

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

Thanks! That's a good point.

@Dogbu-cyber Dogbu-cyber force-pushed the david.ogbureke/extract-tracecontext-appsync branch from f76c2a8 to 6d228b0 Compare January 29, 2026 19:41
@duncanista duncanista requested a review from a team as a code owner February 4, 2026 18:18
@duncanista duncanista requested a review from Copilot February 4, 2026 18:19
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1945 to +1948
assert_eq!(
context.trace_id, 555,
"Should prioritize event.request.headers as service-specific extraction"
);
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The test name test_extract_span_context_priority_order and assertion message claim that event.request.headers should be prioritized, but the implementation shows it's actually checked after event.headers (line 1075). The trace_id assertion expects 555 (from event.request.headers) but based on the extraction order, it should extract 333 from event.headers first. Either the test assertion is incorrect, or the implementation order needs adjustment.

Copilot uses AI. Check for mistakes.
Copy link
Author

@Dogbu-cyber Dogbu-cyber Feb 4, 2026

Choose a reason for hiding this comment

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

This is expected behavior?
Extraction from managed services (including Appsync) is higher priority than trace context within event.headers.

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe it just bugged due to the changes

Comment on lines 1066 to 1073
if let Some(request_obj) = payload_value.get("request") {
if let Some(request_headers) = request_obj.get("headers") {
if let Some(sc) = propagator.extract(request_headers) {
debug!("Extracted trace context from event.request.headers");
return Some(sc);
}
}
}
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

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

The new extraction from event.request.headers is positioned before event.headers (line 1075), which changes the extraction priority. Based on the PR description stating this is a 'fallback', it should be placed after event.headers extraction, not before. This ordering makes it higher priority than top-level event headers, which contradicts the fallback concept.

Copilot uses AI. Check for mistakes.
@Dogbu-cyber Dogbu-cyber changed the title [APMSVLS-197] Add fallback to extract trace context from event.request.headers [APMSVLS-197] Add check to extract trace context present within event.request.headers Feb 4, 2026
Comment on lines 1066 to 1067
if let Some(request_obj) = payload_value.get("request") {
if let Some(request_headers) = request_obj.get("headers") {
Copy link
Contributor

Choose a reason for hiding this comment

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

Can be simplified instead of having two nested if let somes to and_then

Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe even with the third one, depending on what clippy says

}

#[test]
fn test_extract_span_context_appsync_real_world_example() {
Copy link
Contributor

Choose a reason for hiding this comment

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

bad naming with "real_world_example" instead, either set all trace context values to be something useful

Comment on lines 2084 to 2106
let payload = json!({
"arguments": {
"userId": "12345"
},
"identity": {
"sub": "user-sub-id"
},
"request": {
"headers": {
"x-datadog-trace-id": "123456789012345",
"x-datadog-parent-id": "98765432109876",
"x-datadog-sampling-priority": "2",
"x-datadog-origin": "rum",
"x-datadog-tags": "_dd.p.dm=-0",
"user-agent": "Mozilla/5.0",
"content-type": "application/json"
}
},
"info": {
"fieldName": "getUser",
"parentTypeName": "Query"
}
});
Copy link
Contributor

Choose a reason for hiding this comment

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

Could be part of the payloads we have in testing as a file

Copy link
Contributor

@duncanista duncanista left a comment

Choose a reason for hiding this comment

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

Left some more comments

…sts. Removed redundant tests that would be caught by others. Priority and functionality is entirely covered within test_extract_span_context_priority_order.
@Dogbu-cyber Dogbu-cyber requested a review from Copilot February 5, 2026 20:58
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1884 to +1885
context.trace_id, 555,
"Should prioritize event.request.headers as service-specific extraction"
Copy link

Copilot AI Feb 5, 2026

Choose a reason for hiding this comment

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

The test assertion comment claims event.request.headers should be prioritized, but according to the implementation, event.request.headers is checked after trigger-specific headers and before event.headers. With the test data showing headers containing trace_id=111, the actual priority would favor the trigger-specific headers first. The test should either verify that trace_id=111 is extracted (if headers are checked first), or the test data should be adjusted to only include event.request.headers to properly validate this extraction path.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants