fix(native-spans): span-meta language, lazy transport requires, /v0.6/stats slash, IPv6 host#168
Merged
Conversation
Overall package sizeSelf size: 30.09 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------|🤖 This report was automatically generated by heaviest-objects-in-the-universe |
… lang The change buffer's process_span stamps span.meta["language"] from the tracer_language passed to ChangeBufferState, which was the `lang` argument. dd-trace-js passes lang="nodejs" (the Datadog-Meta-Lang header value that identifies the tracer library) but the span-meta language tag must be "javascript" for the Node.js tracer (matching the JS pipeline's span_format and system-tests test_meta_language_tag). Pass "javascript" as the span-meta language while leaving set_language(lang) and StatsMeta.lang untouched.
0ef1e80 to
46f1648
Compare
The Node HTTP transport eagerly required node:http/https/fs at module load. Because this module is loaded during dd-trace-js's own tracer init (before user code), and dd-trace instruments builtins by wrapping them in place when they're required through its hook, the eager require made http get wrapped during init. A user ESM app that then imports http (e.g. under --require) saw the wrapped builtin and got instrumented when it must not, breaking dd-trace-js's init/guardrail expectations (~10 Platform + guardrails checks). Require node:http/https inside httpRequest and node:fs inside detectEntityHeaders (their only consumers), so nothing instrumentable is loaded until the first agent send \u2014 matching the JS agent exporter's lazy timing.
46f1648 to
b5a9a6a
Compare
The stats sender concatenated agent_url + "/v0.6/stats". agent_url normally ends in "/" (Node's URL.toString() normalizes a bare authority that way), so the request path became "//v0.6/stats". The agent records the raw request path, so stats tooling and the test-agent (which match "/v0.6/stats" exactly) miss the request entirely — client stats appear to never arrive. Trim the trailing slash so the path is exactly "/v0.6/stats".
b5a9a6a to
81e17c9
Compare
libdatadog derives the request host from the agent URI, which keeps the brackets for an IPv6 literal (e.g. `[::1]`). Node's `http.request` treats the `host` option as a name to resolve, so `[::1]` fails with `getaddrinfo ENOTFOUND [::1]` and traces never reach an IPv6 agent (the system-tests ipv6 scenario: "No trace has been found"). Strip the surrounding brackets in httpRequest so the IPv6 address is used directly (Node accepts `::1`).
81e17c9 to
1245e94
Compare
ekump
approved these changes
Jul 10, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Four small native-spans fixes that unblock dd-trace-js system-tests / init guardrails / v0.6 stats / IPv6 on the native-spans branch (#9139).
1. span-meta
language→javascriptprocess_spanstampedspan.meta["language"]fromChangeBufferState'stracer_language(= thelangarg ="nodejs", theDatadog-Meta-Langheader value). The span-metalanguagetag must be"javascript"for the Node.js tracer (matching the JS pipeline'sspan_formatand system-teststest_meta_language_tag). Pass"javascript"for the span meta; header +StatsMeta.languntouched.2. Lazy-require
node:http/node:https/node:fsin the transportThe transport eagerly required these builtins at module load. It loads during dd-trace-js's own tracer init (before user code), and dd-trace instruments builtins by wrapping them in place when required through its hook — so
httpgot wrapped during init, and a user ESM app that then importshttp(e.g. under--require) got instrumented when it must not (breaksinit.spec.js"should not initialize ESM instrumentation", ~10 Platform + guardrails checks). Require them lazily insidehttpRequest/detectEntityHeaders.3. Avoid double slash in the
/v0.6/statsURLStats URL was
format!("{}{}", agent_url, "/v0.6/stats");agent_url(URL.toString()) ends in/, so the path became//v0.6/stats. The agent records the raw path and stats tooling matches/v0.6/statsexactly, so client stats silently never arrived (root cause of the 0-stats parametric + resource_renaming E2E failures). Trim the trailing slash.4. Strip IPv6 brackets from the transport host
libdatadog derives the connect host from the agent URI, keeping the brackets for an IPv6 literal (
[::1]). Node'shttp.requesttreatshostas a name to resolve, so[::1]→getaddrinfo ENOTFOUND [::1]and traces never reach an IPv6 agent (system-tests ipv6 "No trace has been found", 5 shards). Strip the brackets for the TCP connect target; the pre-renderedHost:header keeps them (RFC 3986).Known follow-ups (not in this PR): span-event array attributes and span_events-as-tag are dd-trace-js-side (the binding already supports typed array attrs).