Skip to content

fix(profiling): link span to worker thread profile#18089

Merged
gh-worker-dd-mergequeue-cf854d[bot] merged 10 commits into
mainfrom
gyuheon0h/PROF-12202-worker-thread-pool-link
May 20, 2026
Merged

fix(profiling): link span to worker thread profile#18089
gh-worker-dd-mergequeue-cf854d[bot] merged 10 commits into
mainfrom
gyuheon0h/PROF-12202-worker-thread-pool-link

Conversation

@gyuheon0h
Copy link
Copy Markdown
Contributor

@gyuheon0h gyuheon0h commented May 14, 2026

PROF-12202

Summary

Fixes profiler span linkage for ThreadPoolExecutor (and other concurrent.futures) worker threads so CPU samples appear in span-to-profile flame graphs with the correct span id, local root span id, and trace type.

The stack profiler maintains ThreadSpanLinks thorugh stack.link_span(). Previously it only handled Span activations.

The futures integration propagates traces across threads with a Context (tracer._activate_context), not a Span. link_span was a no-op for Context, so worker threads were never registered. Their samples had no span id label and did not show up in span-to-profile views.

  1. link_span handles Context
    When a Context with span_id is activated, call the native linker with

    • span id from context.span_id (parent at submit time)
    • local root span id from internal _meta, or span_id if absent
    • span type from _meta when present
  2. Profiler linkage using Context._meta (futures path)
    Profiler fields are set using internal meta keys _dd.profiling.local_root_span_id and _dd.profiling.span_type
    On executor.submit, when an active span exists:

    • Shallow-copy Context for the worker
    • attach_profiler_link() writes meta on a copied _meta dict; this make sure parent context is unchanged. Values come from current_span._local_root so nested spans still get the true trace root.
    • read_profiler_link() is used in link_span(Context) on the worker.
  3. Child spans in workers
    Spans created in a worker with tracer.trace() have _parent is None but parent_id set. Their local root would incorrectly be the child itself. On Context activation we store local root + span type in thread-local and link_span() uses that for context-propagated children.

Testing

Risks

Additional Notes

Copy link
Copy Markdown
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@gyuheon0h gyuheon0h changed the title Link span to worker thread fix(profiling): link span to worker thread May 14, 2026
@cit-pr-commenter-54b7da
Copy link
Copy Markdown

cit-pr-commenter-54b7da Bot commented May 14, 2026

Codeowners resolved as

ddtrace/contrib/internal/futures/threading.py                           @DataDog/apm-core-python @DataDog/apm-idm-python
ddtrace/internal/datadog/profiling/context_meta.py                      @DataDog/profiling-python
ddtrace/internal/datadog/profiling/stack/__init__.py                    @DataDog/profiling-python
ddtrace/internal/datadog/profiling/stack/_stack.pyi                     @DataDog/profiling-python
releasenotes/notes/profile-worker-thread-pool-span-link-743d71608f01cc56.yaml  @DataDog/apm-python
tests/contrib/futures/test_propagation.py                               @DataDog/apm-core-python @DataDog/apm-idm-python
tests/profiling/collector/test_stack_threadpool.py                      @DataDog/profiling-python
tests/profiling/test_context_meta.py                                    @DataDog/profiling-python
tests/tracer/test_context.py                                            @DataDog/apm-sdk-capabilities-python @DataDog/apm-core-python

@gyuheon0h gyuheon0h marked this pull request as ready for review May 14, 2026 20:30
@gyuheon0h gyuheon0h requested review from a team as code owners May 14, 2026 20:30
Copy link
Copy Markdown

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

Reviewed commit: bb0b8c0171

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread ddtrace/internal/datadog/profiling/stack/__init__.py
@gyuheon0h gyuheon0h force-pushed the gyuheon0h/PROF-12202-worker-thread-pool-link branch from bb0b8c0 to dda374c Compare May 14, 2026 20:49
@pr-commenter
Copy link
Copy Markdown

pr-commenter Bot commented May 14, 2026

Benchmarks

Benchmark execution time: 2026-05-19 15:13:33

Comparing candidate commit 00827a8 in PR branch gyuheon0h/PROF-12202-worker-thread-pool-link with baseline commit f0f5ba0 in branch main.

Found 0 performance improvements and 2 performance regressions! Performance is the same for 364 metrics, 9 unstable metrics.

scenario:span-start

  • 🟥 execution_time [+1.445ms; +1.638ms] or [+9.274%; +10.509%]

scenario:telemetryaddmetric-1-count-metric-1-times

  • 🟥 execution_time [+209.553ns; +247.410ns] or [+10.043%; +11.857%]

Copy link
Copy Markdown
Collaborator

@wantsui wantsui left a comment

Choose a reason for hiding this comment

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

LGTM from an idm perspective. Do you need release notes for this fix?

@gyuheon0h gyuheon0h changed the title fix(profiling): link span to worker thread fix(profiling): link span to worker thread profile May 15, 2026
Copy link
Copy Markdown
Contributor

@KowalskiThomas KowalskiThomas left a comment

Choose a reason for hiding this comment

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

This is very cool. I'm really not an expert on the span <-> profile linking stuff, but I really like this for context propagation 🤩

Comment thread ddtrace/internal/datadog/profiling/stack/__init__.py Outdated
Comment thread ddtrace/internal/datadog/profiling/stack/__init__.py Outdated
@gyuheon0h gyuheon0h force-pushed the gyuheon0h/PROF-12202-worker-thread-pool-link branch from dda374c to 0c5bdc9 Compare May 15, 2026 13:57
Copy link
Copy Markdown

@anthonypalmeira anthonypalmeira left a comment

Choose a reason for hiding this comment

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

Thanks for taking care of this

@gyuheon0h gyuheon0h requested review from mabdinur and rachelyangdog and removed request for mabdinur May 18, 2026 14:27
@gyuheon0h gyuheon0h force-pushed the gyuheon0h/PROF-12202-worker-thread-pool-link branch from f31e255 to 382da82 Compare May 18, 2026 14:55
@gyuheon0h gyuheon0h requested a review from a team as a code owner May 18, 2026 14:55
@gyuheon0h gyuheon0h force-pushed the gyuheon0h/PROF-12202-worker-thread-pool-link branch from 11b13c1 to 8a4c02c Compare May 18, 2026 21:46
Comment thread ddtrace/contrib/internal/futures/threading.py Outdated
@gyuheon0h gyuheon0h requested a review from brettlangdon May 19, 2026 14:36
@datadog-prod-us1-5
Copy link
Copy Markdown
Contributor

datadog-prod-us1-5 Bot commented May 19, 2026

Pipelines  Tests

Fix all issues with BitsAI

⚠️ Warnings

🚦 8 Pipeline jobs failed

DataDog/apm-reliability/dd-trace-py | build linux serverless: [arm64, cp315-cp315, v113741357-d2b8243-manylinux2014_aarch64, 1]   View in Datadog   GitLab

🔧 Fix in code (Fix with Cursor). Smoke test assertion error. Failed with DD_IAST_ENABLED=0 at native module load test.

DataDog/apm-reliability/dd-trace-py | build linux: [arm64, cp315-cp315, v113741589-d2b8243-musllinux_1_2_aarch64]   View in Datadog   GitLab

🔧 Fix in code (Fix with Cursor). AssertionError: Failed with DD_IAST_ENABLED=0: 1 while running module load test.

DataDog/apm-reliability/dd-trace-py | build linux serverless: [arm64, cp315-cp315, v113741589-d2b8243-musllinux_1_2_aarch64, 1]   View in Datadog   GitLab

🔄 Retry job. This looks flaky and may succeed on retry. Startup probe failed with status code 503. Containers with unready status: [emissary build helper] and incomplete status: [emissary init-permissions].

View all 8 failed jobs.

ℹ️ Info

No other issues found (see more)

🧪 All tests passed
❄️ No new flaky tests detected

Useful? React with 👍 / 👎

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: a13da98 | Docs | Datadog PR Page | Give us feedback!

@gyuheon0h gyuheon0h force-pushed the gyuheon0h/PROF-12202-worker-thread-pool-link branch from cf2a19b to 00827a8 Compare May 19, 2026 14:50
Comment thread ddtrace/_trace/context.py Outdated
Copy link
Copy Markdown
Contributor

@mabdinur mabdinur 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 questions and nits. Overall looks good

Comment thread ddtrace/internal/datadog/profiling/stack/__init__.py Outdated
Comment thread ddtrace/_trace/context.py Outdated
Comment thread ddtrace/_trace/context.py
Comment thread ddtrace/contrib/internal/futures/threading.py
@gyuheon0h gyuheon0h force-pushed the gyuheon0h/PROF-12202-worker-thread-pool-link branch from b78f118 to e236612 Compare May 19, 2026 22:31
@gyuheon0h gyuheon0h force-pushed the gyuheon0h/PROF-12202-worker-thread-pool-link branch from e236612 to 85841d7 Compare May 20, 2026 15:14
@gyuheon0h gyuheon0h force-pushed the gyuheon0h/PROF-12202-worker-thread-pool-link branch from 47f7fc4 to 3508889 Compare May 20, 2026 16:15
@gh-worker-dd-mergequeue-cf854d gh-worker-dd-mergequeue-cf854d Bot merged commit b83f6f3 into main May 20, 2026
524 checks passed
@gh-worker-dd-mergequeue-cf854d gh-worker-dd-mergequeue-cf854d Bot deleted the gyuheon0h/PROF-12202-worker-thread-pool-link branch May 20, 2026 18:52
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.

6 participants