Skip to content

feat(otel-thread-ctx)!: add shared thread context - #2168

Open
yannham wants to merge 8 commits into
mainfrom
yannham/thread-ctx-shared
Open

feat(otel-thread-ctx)!: add shared thread context#2168
yannham wants to merge 8 commits into
mainfrom
yannham/thread-ctx-shared

Conversation

@yannham

@yannham yannham commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

This PR adds a different shared ownership model for the OTel thread context record, in addition the the current API that only supports owned context records. Doing so, we split the interface into corresponding owned and shared submodules.

Since the two modes are incompatible (trying to attach/detach in one mode and doing the other operation in the other mode is basically UB), the two modes are feature-gated in a way such that they can't co-exist (if both features are set, owned wins).

The FFI is left unchanged (from the point of view of an external consumer at least).

Motivation

We want to integrate the work in dd-trace-rs. The current API assumes that the context is a heap-allocated, uniquely owned piece (which is indeed required for the update API). However, given open-telemetry/opentelemetry-rust#3585, this won't work for dd-trace-rs, where the context will be an immutable shared Arc.

There are two possible solutions:

  1. expose lower-level, unsafe internals and let dd-trace-rs play with pointers conversions and handle the refcounting part. More flexible in some sense (not Arc-specific), but more dangerous.
  2. since we'll likely never need anything else beyond the current box-owned and the new arc-shared in practice, we can make a second safe Arc-based API. This is the option I've picked.

Additional Notes

For reviewers: I've split the existing codebase, but almost all of the new code should be located in shared.rs. owned.rs is just part of the previous API but renamed, with just a few functions factorized in linux.rs as they are now used from both modules. Same for the FFI: beside moving ThreadContextHandle directly there, no major changes here.

How to test the change?

tests included.

@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

📚 Documentation Check Results

⚠️ 281 documentation warning(s) found

📦 libdd-otel-thread-ctx-ffi - 280 warning(s)

📦 libdd-otel-thread-ctx - 1 warning(s)


Updated: 2026-09-11 13:59:05 UTC | Commit: 3161204 | missing-docs job results

@github-actions

github-actions Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

🔒 Cargo Deny Results

No issues found!

📦 libdd-otel-thread-ctx-ffi - ✅ No issues

📦 libdd-otel-thread-ctx - ✅ No issues


Updated: 2026-09-11 14:00:51 UTC | Commit: 3161204 | dependency-check job results

@datadog-prod-us1-4

datadog-prod-us1-4 Bot commented Jun 26, 2026

Copy link
Copy Markdown

🎯 Code Coverage (details)
Patch Coverage: 92.21%
Overall Coverage: 77.74% (-0.04%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 0ae31cc | Docs | View more details | Give us feedback!

@dd-octo-sts

dd-octo-sts Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Artifact Size Benchmark Report

aarch64-alpine-linux-musl
Artifact Baseline Commit Change
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.a 96.01 MB 96.01 MB 0% (0 B) 👌
/aarch64-alpine-linux-musl/lib/libdatadog_profiling.so 9.02 MB 9.02 MB 0% (0 B) 👌
aarch64-unknown-linux-gnu
Artifact Baseline Commit Change
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.so 12.19 MB 12.19 MB 0% (0 B) 👌
/aarch64-unknown-linux-gnu/lib/libdatadog_profiling.a 107.42 MB 107.42 MB 0% (0 B) 👌
libdatadog-x64-windows
Artifact Baseline Commit Change
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.dll 29.04 MB 29.04 MB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.lib 96.08 KB 96.08 KB 0% (0 B) 👌
/libdatadog-x64-windows/debug/dynamic/datadog_profiling_ffi.pdb 191.77 MB 191.77 MB 0% (0 B) 👌
/libdatadog-x64-windows/debug/static/datadog_profiling_ffi.lib 818.19 MB 818.19 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.dll 9.69 MB 9.69 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.lib 96.08 KB 96.08 KB 0% (0 B) 👌
/libdatadog-x64-windows/release/dynamic/datadog_profiling_ffi.pdb 27.51 MB 27.51 MB 0% (0 B) 👌
/libdatadog-x64-windows/release/static/datadog_profiling_ffi.lib 55.57 MB 55.57 MB 0% (0 B) 👌
libdatadog-x86-windows
Artifact Baseline Commit Change
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.dll 25.41 MB 25.41 MB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.lib 97.58 KB 97.58 KB 0% (0 B) 👌
/libdatadog-x86-windows/debug/dynamic/datadog_profiling_ffi.pdb 197.07 MB 197.08 MB +0% (+8.00 KB) 👌
/libdatadog-x86-windows/debug/static/datadog_profiling_ffi.lib 800.48 MB 800.48 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.dll 7.51 MB 7.51 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.lib 97.58 KB 97.58 KB 0% (0 B) 👌
/libdatadog-x86-windows/release/dynamic/datadog_profiling_ffi.pdb 29.63 MB 29.63 MB 0% (0 B) 👌
/libdatadog-x86-windows/release/static/datadog_profiling_ffi.lib 52.55 MB 52.55 MB 0% (0 B) 👌
x86_64-alpine-linux-musl
Artifact Baseline Commit Change
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.a 85.97 MB 85.97 MB 0% (0 B) 👌
/x86_64-alpine-linux-musl/lib/libdatadog_profiling.so 10.03 MB 10.03 MB 0% (0 B) 👌
x86_64-unknown-linux-gnu
Artifact Baseline Commit Change
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.a 101.85 MB 101.85 MB 0% (0 B) 👌
/x86_64-unknown-linux-gnu/lib/libdatadog_profiling.so 12.25 MB 12.25 MB 0% (0 B) 👌

Base automatically changed from yannham/thread-ctx-autocheck to main June 29, 2026 14:42
@yannham
yannham force-pushed the yannham/thread-ctx-shared branch from 003ab9e to 4f07a3b Compare July 1, 2026 11:58
@yannham
yannham force-pushed the yannham/thread-ctx-shared branch from 79d5158 to 040545c Compare September 11, 2026 12:07
@pr-commenter

pr-commenter Bot commented Sep 11, 2026

Copy link
Copy Markdown

Benchmarks

Comparison

Candidate

Candidate benchmark details

Baseline

Baseline benchmark details

@yannham
yannham marked this pull request as ready for review September 11, 2026 12:40
@yannham
yannham requested review from a team as code owners September 11, 2026 12:40
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 11, 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-11T12:46:19.695471Z 5664764 Draft marked ready
ℹ️ 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 chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

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: 56647649f3

ℹ️ 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 +27 to +30
#[cfg(all(feature = "shared-context", not(feature = "owned-context")))]
mod shared;
#[cfg(all(feature = "shared-context", not(feature = "owned-context")))]
pub use shared::*;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve the shared API after Cargo feature unification

When a final binary contains a shared-mode consumer alongside any dependency that enables the default owned-context feature—such as libdd-otel-thread-ctx-ffi—Cargo unifies both features, and this condition removes SharedThreadContext even though shared-context was requested. The shared consumer then fails to compile with an unresolved import; the shared-only and all-features CI runs cannot expose this mixed dependency case. Use a design that remains composable under additive feature unification, such as separate packages for the incompatible modes.

AGENTS.md reference: AGENTS.md:L76-L81

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is on purpose. I can't prevent separate packages from being used together. It's not ideal to have "falsely additive" features like that, but is the only way I know in Rust unfortunately have this kind of static exclusion policy guaranteeing that one can never use both APIs at the same time.

// Though our `SharedThreadContext` might actually come from a different thread now, it's
// wrapped in an `Arc` that handles drop safety by synchronizing on the reference count. The
// record is already `valid = 1` and, being shared, immutable.
let record_ptr = Arc::into_raw(self.0) as *mut ThreadContextRecord;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Release the attached Arc when its thread exits

If a thread terminates while a shared context is still attached—for example, because its task panics before calling detach—the strong reference converted here is lost when the raw assembly TLS slot is destroyed, because no TLS destructor ever reconstructs the Arc. Repeated short-lived threads therefore leak one 640-byte context allocation each (and any context attached on several exiting threads retains every leaked reference); add thread-exit cleanup or an RAII attachment guard that reliably reclaims the slot reference.

AGENTS.md reference: AGENTS.md:L77-L82

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It's a legitimate concern, but unrelated to this PR IMHO. Was already the case for the previous owned API. I guess we can use a Rust thread-local dummy variable just for cleanup. Will consider this in a follow-up, if that sounds reasonable to reviewers

@yannham yannham changed the title feat(otel-thread-ctx): add shared thread context feat(otel-thread-ctx)!: add shared thread context Sep 11, 2026
…on-Linux

The shared-context nextest invocation ran unconditionally on all runners,
but libdd-otel-thread-ctx's functionality (and tests) are Linux-only, so
macOS/Windows runners find zero tests and nextest exits with "no tests to
run" (exit code 4).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant