Skip to content

feat: extract trace context from MSK events - #830

Closed
lucassarcanjo wants to merge 3 commits into
DataDog:mainfrom
lucassarcanjo:feat/msk-trace-extraction
Closed

lucassarcanjo wants to merge 3 commits into
DataDog:mainfrom
lucassarcanjo:feat/msk-trace-extraction

Conversation

@lucassarcanjo

@lucassarcanjo lucassarcanjo commented Sep 8, 2026 •

Copy link
Copy Markdown

What does this PR do?

Adds automatic trace context extraction for MSK-triggered Lambdas. Kafka header byte arrays are decoded as UTF-8 and passed to the existing tracer, preserving Datadog and W3C propagation context.

For batches, the Lambda span uses the first record with valid trace context across the topic-partition groups. Malformed headers are skipped, and headers from different records are never combined.

Motivation

Fixes #829. An instrumented producer's trace headers reach the Lambda event, but the existing dispatcher does not extract them, so the Lambda starts a separate trace.

Testing Guidelines

  • yarn test --runInBand: 691 tests and 3 snapshots passed on Node.js 22.
  • yarn lint and formatting checks passed.
  • Local Node.js 24 check with real dd-trace@5.118.0: the Lambda tracing lifecycle preserves the producer parent ID, sampling priority, and 128-bit trace ID with Datadog-only, W3C-only, and combined headers. The same reproduction fails with the original dispatcher.
  • Live AWS/MSK and Docker integration validation are pending.

Types of Changes

  • New feature

Check all that apply

  • This PR's description is comprehensive
  • This PR's changes are covered by the automated tests
  • This PR passes the integration tests (ask a Datadog member to run the tests)

Comment thread src/trace/context/extractors/msk.ts
@lucassarcanjo
lucassarcanjo marked this pull request as ready for review September 9, 2026 12:11
@lucassarcanjo
lucassarcanjo requested review from a team as code owners September 9, 2026 12:11
@lucassarcanjo
lucassarcanjo requested a review from lym953 September 9, 2026 12:11

@BridgeAR BridgeAR left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for the PR! I just left a few suggestions to make the code a bit faster :)

Comment thread src/trace/context/extractors/msk.ts Outdated
Comment thread src/trace/context/extractors/msk.ts Outdated
Comment thread src/trace/context/extractors/msk.ts Outdated
Comment thread src/trace/context/extractors/msk.ts Outdated

@BridgeAR BridgeAR left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for the quick follow-ups!

Code wise it seems fine to me.

@lucassarcanjo

Copy link
Copy Markdown
Author

Hi @lym953, could you take a look at this PR?

@jcstorms1

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@jcstorms1

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-15T19:58:31.341873Z c552877 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

Reviewed commit: c552877bb5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@jcstorms1

Copy link
Copy Markdown
Contributor

LGTM 👍

@zarirhamza

Copy link
Copy Markdown
Contributor

Thanks @lucassarcanjo! This looks good to us but we need you to rebase onto the original main branch instead of a fork. If you'd rather us take care of it, please enable allow edits from maintainers so we can rebase and merge

@lucassarcanjo
lucassarcanjo force-pushed the feat/msk-trace-extraction branch from c552877 to b6dd184 Compare September 15, 2026 23:44
@lucassarcanjo

Copy link
Copy Markdown
Author

Hi @zarirhamza, done!

- Guard event.records with an early return instead of an empty fallback
- Wrap the record loop in a single try/catch so errors log once
- Return null from getParsedRecordHeaders when nothing decodes, lazily
  creating the headers map
- Drop per-byte validation and rely on Buffer.from
@zarirhamza

Copy link
Copy Markdown
Contributor

/remove

@gh-worker-devflow-routing-ef8351

gh-worker-devflow-routing-ef8351 Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

View all feedbacks in Devflow UI.

2026-09-17 13:15:41 UTC ℹ️ Start processing command /remove


2026-09-17 13:15:49 UTC ℹ️ Devflow: /remove

event.records !== null &&
typeof event.records === "object" &&
!Array.isArray(event.records)
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Lambda's self-managed Kafka trigger (any non-MSK cluster, e.g. on EC2 or Confluent Cloud) sends the same records and headers shape as MSK, but with eventSource: "SelfManagedKafka". Right now isMSKEvent only accepts "aws:kafka"`, so those Lambdas would still start a disconnected trace.

Could we accept both values?

static isKafkaEvent(event: any): event is MSKEvent | SelfManagedKafkaEvent {
  return (
    (event?.eventSource === "aws:kafka" || event?.eventSource === "SelfManagedKafka") &&
    event.records !== null &&
    typeof event.records === "object" &&
    !Array.isArray(event.records)
  );
}

The header-decoding logic should work for both as-is. A test fixture with eventSource: "SelfManagedKafka" would cover it. If self-managed Kafka is intentionally out of scope for this PR, that's fine too. A follow-up issue would be enough.

try {
// A Lambda span can have only one parent. Use the first record with valid
// trace context, without combining headers from different records.
for (const records of Object.values(event.records)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Every other batch extractor takes trace context from the first record only: sqs.ts, sns.ts, sns-sqs.ts, event-bridge-sqs.ts, and kinesis.ts all use Records[0]. Their loops over every record are only for DSM checkpoints. Can we do the same here? Read the first record of the first topic-partition, try to extract from it, and return.

This keeps MSK consistent with the other event sources, so the Lambda span's parent is always the first record. It also avoids decoding headers and calling tracer.extract on up to 10k records in every untraced batch.

The test cases that expect a later record's context to win would need to change to expect null.

@purple4reina purple4reina left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hi, just the two comments. Then I'll work to make sure the tests pass and we can get this merged. 😄

@purple4reina

Copy link
Copy Markdown
Contributor

Sorry, there's too many datadog cooks in the kitchen, looks like we're all giving you different instructions. My apologies for any confusion.

@purple4reina

Copy link
Copy Markdown
Contributor

Oh wow, my bad. Looks like this was all already merged in #838. I'm gonna go ahead and close this PR. Thank you again for your help!

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.

Built-in trace context extraction for MSK-triggered Lambdas

5 participants