Skip to content

feat!: expose ThreadLocalMetadata via process_discovery#153

Open
szegedi wants to merge 2 commits into
mainfrom
szegedi/threadlocal-metadata
Open

feat!: expose ThreadLocalMetadata via process_discovery#153
szegedi wants to merge 2 commits into
mainfrom
szegedi/threadlocal-metadata

Conversation

@szegedi

@szegedi szegedi commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Exposes the new ThreadLocalMetadata shape from libdatadog's libdd-library-config (introduced in DataDog/libdatadog#2162) via process_discovery, so tracers building against libdatadog-nodejs can drive the full threadlocal.* block of the OTel process context — not just the attribute key map.

Changes

crates/process_discovery/Cargo.toml

  • Bumped libdd-library-config from tag = "v35.0.0" to rev = "7cdeb7896e92d1ba38bde495934e112dac2eda25" (the merge commit of libdatadog#2162). Swap back to a tagged release once one that includes this commit is published.
  • Added a direct dep on libdd-trace-protobuf (at the same rev) to reach any_value::Value when converting caller-supplied extras.

crates/process_discovery/src/lib.rs

  • Replaced the flat threadlocal_attribute_keys: Option<Vec<String>> field on the napi TracerMetadata with threadlocal_metadata: Option<ThreadLocalMetadata>.
  • Two new #[napi(object)] types mirroring the upstream shape:
    • ThreadLocalMetadata { attribute_keys, schema_version, extra_attributes } — drives the threadlocal.* block; null/omitted disables the block entirely.
    • ExtraAttribute { key, string_value?, int_value? } — one KeyValue for the process context. Exactly one of string_value / int_value should be set; entries with neither are silently dropped. Only string and 64-bit int are exposed for now — the other AnyValue variants (bool, double, bytes, array, kvlist) can be added later as needed.

Test plan

  • yarn build-debug && node test/process-discovery.js locally
  • Downstream migration in dd-trace-js — the tracer-metadata construction there needs to switch from passing threadlocalAttributeKeys to a threadlocalMetadata object

Follow-up

Once libdatadog cuts a release that includes 7cdeb7896e92d1ba38bde495934e112dac2eda25, replace the git-rev deps with a tagged version.

Jira: PROF-15221

Replaces the flat `threadlocal_attribute_keys` field on the napi
TracerMetadata with a `threadlocal_metadata` substruct mirroring the
libdatadog Rust API. Lets callers set the schema-version string and
extra process-context attributes (strings and 64-bit ints for now)
alongside the attribute key map.

libdd-library-config and libdd-trace-protobuf are pinned to the merge
commit that introduced the new API (7cdeb7896e92d1ba38bde495934e112dac2eda25);
swap back to a tagged release once one that includes it is published.

This is a breaking change to the process_discovery.TracerMetadata
constructor. Downstream (dd-trace-js) will need to migrate from passing
threadlocalAttributeKeys directly to passing a threadlocalMetadata
object.
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

Overall package size

Self size: 28.12 MB
Deduped: 28.12 MB
No deduping: 28.12 MB

Dependency sizes | name | version | self size | total size | |------|---------|-----------|------------|

🤖 This report was automatically generated by heaviest-objects-in-the-universe

@szegedi szegedi marked this pull request as ready for review July 1, 2026 15:14
@szegedi szegedi requested review from a team as code owners July 1, 2026 15:14
gyuheon0h
gyuheon0h previously approved these changes Jul 1, 2026
/// Extra `threadlocal.*` attributes to publish alongside the key map (e.g.
/// V8 layout constants a Node.js reader needs to walk from the discovery
/// TLS symbol into the record).
pub extra_attributes: Vec<ExtraAttribute>,

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.

should this be optional?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I would think an empty vec is ok here, unless you really need to differentiate None from Some(vec![]) for some reason. Or do you ask with respect to null support or something related to JS-Rust interop?

Comment thread crates/process_discovery/src/lib.rs Outdated
}

fn convert_extra_attribute(ea: &ExtraAttribute) -> Option<(String, any_value::Value)> {
let value = if let Some(s) = &ea.string_value {

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.

The doc on line 16-17 say set exactly one but this function prefers string value. Should this be surfaced or is this okay?

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.

Maybe the API contract is the doc 🤷, but just noting that the program itself has behavior that is not surfaced just by "set exactly one"

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.

Oh you mean how we aren't checking for when both are set? Yeah, it'd be polite to throw an error instead of ignoring the int value. I'll do that.

yannham
yannham previously approved these changes Jul 1, 2026
Comment on lines +24 to +25
pub string_value: Option<String>,
pub int_value: Option<i64>,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

If we should only have one, then this should be an enum.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ah, I suppose because it has to be mapped to a JS object? In that case please ignore my comment.

/// Extra `threadlocal.*` attributes to publish alongside the key map (e.g.
/// V8 layout constants a Node.js reader needs to walk from the discovery
/// TLS symbol into the record).
pub extra_attributes: Vec<ExtraAttribute>,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I would think an empty vec is ok here, unless you really need to differentiate None from Some(vec![]) for some reason. Or do you ask with respect to null support or something related to JS-Rust interop?

Per review feedback: the previous behavior silently preferred string_value
when both were set and silently dropped the entry when neither was — both
are shapes a caller likely didn't mean. Return an InvalidArg napi::Error
instead, matching the 'exactly one of' docstring. Test both paths.
@szegedi szegedi dismissed stale reviews from yannham and gyuheon0h via e9317f4 July 1, 2026 15:55
@szegedi szegedi requested review from gyuheon0h and yannham July 1, 2026 15:58
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