Skip to content

Conversation

@joeyzhao2018
Copy link
Contributor

@joeyzhao2018 joeyzhao2018 commented Nov 18, 2025

Motivation

https://datadoghq.atlassian.net/browse/APMS-17080

TLDR of this ticket: Based on the customer's debug log, we see that the currentTraceContext is coming from an active span from previous invocation, even though the extraction of trace context worked.

also.. previous PR didn't fix the issue as the tracecontext was not cached as rootTraceContext.

What does this PR do?

  • Clean up the logic around rootTraceContext and currentTraceContext.
    • rootTraceContext should come from the lambda invocation's event and context
    • currentTraceContext can come from the customers' manual instrumentations.
    • When calling trace-context-service.extract
      • rootTraceContext should not use any stale trace context from previous invocations at all.
      • currentTraceContext should not be set at this point and if detected, we'll try to closeScope (This is the customer's issue)

Types of Changes

  • Bug fix
  • New feature
  • Breaking change
  • Misc (docs, refactoring, dependency upgrade, etc.)

Check all that apply

  • This PR's description is comprehensive
  • This PR contains breaking changes that are documented in the description
  • This PR introduces new APIs or parameters that are documented and unlikely to change in the foreseeable future
  • This PR impacts documentation, and it has been updated (or a ticket has been logged)
  • This PR's changes are covered by the automated tests
  • This PR collects user input/sensitive content into Datadog
  • This PR passes the integration tests (ask a Datadog member to run the tests)

@joeyzhao2018 joeyzhao2018 requested review from a team as code owners November 18, 2025 20:31

public closeScope(): void {
try {
const activeSpan = this.currentSpan;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this.currentSpan will check

    if (!this.isTracerAvailable) {
      return;
    }

try {
const activeSpan = this.currentSpan;
if (activeSpan && typeof activeSpan.finish === "function") {
logDebug("Detected stale span from previous invocation, finishing it to prevent trace context leakage");
Copy link
Contributor Author

@joeyzhao2018 joeyzhao2018 Nov 19, 2025

Choose a reason for hiding this comment

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

Honestly, I was thinking this should be logWarning because this is not expected.
But the customer is actively running into this issue and we simply cannot reproduce, warning logs will spam their logs right away.

Since we are still actively working with them. My proposal is that we keep it at DEBUG level for this release => then check with the customer to understand which span was that leaked span => have a good reproduction case and fix it => update this to WARNING level.

@lucaspimentel
Copy link
Member

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull 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".

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".

Comment on lines +99 to +102
const activeSpan = this.currentSpan;
if (activeSpan && typeof activeSpan.finish === "function") {
logDebug("Detected stale span from previous invocation, finishing it to prevent trace context leakage");
activeSpan.finish();

Choose a reason for hiding this comment

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

P2 Badge Closing scope still leaves stale dd-trace context active

The new closeScope() only calls finish() on whatever span is currently active, but it never deactivates or clears that span from the tracer’s scope. TracerWrapper.traceContext() still returns the active span unconditionally, and TraceContextService.currentTraceContext (src/trace/trace-context-service.ts:73-79) always prefers that dd-trace span when injecting headers. In the warm-start scenario this change is trying to fix—an unfinished span left active from a prior invocation—closeScope() will finish the span but leave it active, so currentTraceHeaders will still emit the stale trace IDs. Deactivating the scope or skipping finished spans is needed to prevent the leakage the commit is addressing.

Useful? React with 👍 / 👎.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now the extract will return the extracted context and won't use the current context. later the extracted context will be used to create the inferred span or the lambda span and resetting the tracecontext there. Here the finish() is really trying to finish the still active span.


return this.currentTraceContext;
// Return the extracted context, not the current context which may not be related to the event or context
return this.rootTraceContext;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is the fix that codex missed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants