Skip to content

fix(otel)!: share a single @opentelemetry/api copy with the application - #9077

Draft
BridgeAR wants to merge 15 commits into
masterfrom
BridgeAR/2026-06-26-otel-api-optional-peer
Draft

fix(otel)!: share a single @opentelemetry/api copy with the application#9077
BridgeAR wants to merge 15 commits into
masterfrom
BridgeAR/2026-06-26-otel-api-optional-peer

Conversation

@BridgeAR

@BridgeAR BridgeAR commented Jun 26, 2026

Copy link
Copy Markdown
Member

Summary

dd-trace bundled its own @opentelemetry/api as an optional dependency. The OpenTelemetry global API keys providers per major and rejects one registered by a copy older than the reader's, so once the application loaded a newer copy the bridge's provider lost the version check and every span silently downgraded to a no-op (reported with @opentelemetry/api >1.4.1).

Binding to the application's own copy removes the mismatch: an instrumentation captures @opentelemetry/api and @opentelemetry/api-logs as the application requires them, and every bridge module reads that copy through a holder. There is then exactly one copy, and ESM callers work identically to CommonJS because require-in-the-middle drives the capture.

  1. The packages become optional peer dependencies instead of bundled optional dependencies. Without them the trace bridge throws on first use and the metrics and logs pipelines stay dormant.
  2. Metrics and logs registration defers through an onReady continuation until the copy is captured; the meter provider registers before OTLP runtime metrics so their instruments bind to the real meter, not the noop one.
  3. The esbuild and webpack plugins mark both packages external so bundling leaves the runtime require intact for the instrumentation.

Test plan

  • test/opentelemetry/api.spec.js: the holder captures the first copy, ignores later captures, and runs onReady immediately when captured or defers it in registration order otherwise.
  • datadog-instrumentations/test/otel-api.spec.js: the hooks fire across the supported version ranges and hand the module to the holder unchanged.
  • test/proxy.spec.js: metrics/logs registration defers until capture, and runtime metrics start after the meter provider.
  • Existing opentelemetry, runtime_metrics, and openfeature suites pass with every consumer reading through the holder.

Fixes: #6882

@dd-octo-sts

dd-octo-sts Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Overall package size

Self size: 7.53 MB
Deduped: 8.19 MB
No deduping: 8.19 MB

Dependency sizes | name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.3.2 | 124.41 kB | 440.65 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |

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

@datadog-prod-us1-4

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

Copy link
Copy Markdown

Pipelines  Tests

⚠️ Warnings

🚦 3 Pipeline jobs failed

APM Capabilities | tracing-windows   View in Datadog   GitHub Actions

Platform | integration-guardrails (22.0.0)   View in Datadog   GitHub Actions

All Green | all-green   View in Datadog   GitHub Actions

❄️ 1 New flaky test detected

    resolves application copies from a directory entrypoint from Mocha Tests   View in Datadog

View in Flaky Test Management

ℹ️ Info

No other issues found (see more)

🧪 All tests passed

🔄 Datadog auto-retried 1 job - 1 passed on retry View in Datadog

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 98.45% (+0.01%)

Useful? React with 👍 / 👎

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

@pr-commenter

pr-commenter Bot commented Jun 26, 2026

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-07-22 12:14:19

Comparing candidate commit 9a14ac1 in PR branch BridgeAR/2026-06-26-otel-api-optional-peer with baseline commit 293cf61 in branch master.

📊 Benchmarking dashboard

Found 0 performance improvements and 0 performance regressions! Performance is the same for 2326 metrics, 32 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

Unstable benchmarks

These benchmarks have a confidence interval too wide to call a change; treat them as noise rather than signal.

scenario:appsec-appsec-enabled-24

  • unstable execution_time [-205.108ms; +207.446ms] or [-7.698%; +7.786%]

scenario:appsec-appsec-enabled-26

  • unstable execution_time [-238.317ms; +243.917ms] or [-9.320%; +9.538%]

scenario:appsec-appsec-enabled-with-attacks-24

  • unstable execution_time [-160.609ms; +171.989ms] or [-5.199%; +5.568%]

scenario:appsec-appsec-enabled-with-attacks-26

  • unstable execution_time [-198.410ms; +185.517ms] or [-6.810%; +6.367%]

scenario:appsec-control-20

  • unstable execution_time [-120.583ms; +139.025ms] or [-7.299%; +8.415%]

scenario:appsec-control-24

  • unstable execution_time [-111.263ms; +115.455ms] or [-8.946%; +9.283%]

scenario:appsec-control-26

  • unstable execution_time [-120.480ms; +128.537ms] or [-9.724%; +10.374%]

scenario:appsec-iast-no-vulnerability-control-20

  • unstable execution_time [-13859.060µs; +15704.593µs] or [-5.405%; +6.125%]

scenario:appsec-iast-no-vulnerability-iast-enabled-always-active-20

  • unstable execution_time [-17042.513µs; +15432.646µs] or [-6.495%; +5.882%]

scenario:appsec-iast-with-vulnerability-control-20

  • unstable execution_time [-33.178ms; +26.092ms] or [-6.012%; +4.728%]

scenario:debugger-line-probe-with-snapshot-default-26

  • unstable cpu_user_time [-2314.601ms; +737.639ms] or [-24.171%; +7.703%]
  • unstable execution_time [-2339.219ms; +737.993ms] or [-22.704%; +7.163%]
  • unstable instructions [-20.4G instructions; +6.6G instructions] or [-25.679%; +8.256%]
  • unstable throughput [-143.734op/s; +460.294op/s] or [-4.466%; +14.301%]

scenario:debugger-line-probe-with-snapshot-minimal-24

  • unstable cpu_user_time [-2788.035ms; +2785.364ms] or [-31.391%; +31.360%]
  • unstable execution_time [-2783.767ms; +2805.710ms] or [-28.996%; +29.225%]
  • unstable instructions [-23893.4M instructions; +23860.3M instructions] or [-32.847%; +32.802%]
  • unstable max_rss_usage [-11267.570KB; +11384.370KB] or [-7.057%; +7.130%]
  • unstable throughput [-745.785op/s; +736.554op/s] or [-21.311%; +21.047%]

scenario:debugger-line-probe-without-snapshot-26

  • unstable cpu_user_time [-2.679s; +5.741s] or [-25.953%; +55.620%]
  • unstable execution_time [-2.657s; +5.762s] or [-24.063%; +52.188%]
  • unstable instructions [-24.0G instructions; +51.4G instructions] or [-27.739%; +59.333%]
  • unstable max_rss_usage [-8.508MB; +18.240MB] or [-5.245%; +11.245%]
  • unstable throughput [-1130.287op/s; +518.797op/s] or [-36.757%; +16.871%]

scenario:dogstatsd-with-tags-20

  • unstable cpu_user_time [-267.132ms; +346.105ms] or [-5.352%; +6.935%]
  • unstable execution_time [-265.779ms; +343.495ms] or [-5.245%; +6.779%]
  • unstable throughput [-123786.365op/s; +93414.608op/s] or [-7.478%; +5.643%]

scenario:plugin-claude-agent-sdk-compact-stream-scan-26

  • unstable cpu_usage_percentage [-6.448%; +3.789%]

scenario:plugin-graphql-long-with-depth-and-collapse-off-20

  • unstable max_rss_usage [-26.334MB; +39.786MB] or [-6.645%; +10.040%]

scenario:plugin-graphql-long-with-depth-off-26

  • unstable max_rss_usage [-23112.087KB; +24541.801KB] or [-10.595%; +11.251%]

scenario:plugin-pg-service-26

  • unstable execution_time [-71.298ms; +35.144ms] or [-7.821%; +3.855%]

scenario:test-optimization-large-suite-20

  • unstable max_rss_usage [-6.350MB; +2.669MB] or [-7.838%; +3.294%]

@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.43%. Comparing base (b81a957) to head (e1c972a).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9077      +/-   ##
==========================================
+ Coverage   98.41%   98.43%   +0.02%     
==========================================
  Files         932      934       +2     
  Lines      124878   125349     +471     
  Branches    10529    10640     +111     
==========================================
+ Hits       122893   123391     +498     
+ Misses       1985     1958      -27     
Flag Coverage Δ
aiguard 58.65% <100.00%> (-0.03%) ⬇️
aiguard-integration 57.02% <65.06%> (+0.04%) ⬆️
apm-bucket-0 58.53% <100.00%> (-0.03%) ⬇️
apm-bucket-1 64.62% <65.06%> (-0.02%) ⬇️
apm-bucket-2 63.68% <100.00%> (-0.03%) ⬇️
apm-bucket-3 60.96% <59.43%> (-0.04%) ⬇️
apm-capabilities-tracing 64.89% <100.00%> (+0.24%) ⬆️
apm-integrations-aerospike 57.66% <100.00%> (-0.03%) ⬇️
apm-integrations-confluentinc-kafka-javascript 62.53% <100.00%> (-0.06%) ⬇️
apm-integrations-couchbase 57.98% <65.06%> (+0.02%) ⬆️
apm-integrations-http 63.66% <100.00%> (-0.02%) ⬇️
apm-integrations-kafkajs 63.13% <100.00%> (-0.03%) ⬇️
apm-integrations-next 60.05% <59.43%> (-0.03%) ⬇️
apm-integrations-prisma 59.66% <84.04%> (+0.15%) ⬆️
appsec 73.98% <100.00%> (+<0.01%) ⬆️
appsec-express_fastify_graphql 71.29% <100.00%> (-0.02%) ⬇️
appsec-integration 51.88% <56.33%> (+0.01%) ⬆️
appsec-kafka_ldapjs_lodash 64.84% <100.00%> (-0.02%) ⬇️
appsec-mongodb-core_mongoose_mysql 68.56% <100.00%> (-0.02%) ⬇️
appsec-next 58.23% <59.43%> (-0.02%) ⬇️
appsec-node-serialize_passport_postgres 68.26% <100.00%> (-0.02%) ⬇️
appsec-sourcing_stripe_template 66.57% <100.00%> (-0.02%) ⬇️
debugger 65.91% <100.00%> (-0.01%) ⬇️
instrumentations-bucket-0 52.35% <100.00%> (-0.03%) ⬇️
instrumentations-bucket-1 61.10% <100.00%> (-0.03%) ⬇️
instrumentations-bucket-10 62.65% <100.00%> (-0.31%) ⬇️
instrumentations-bucket-11 57.52% <100.00%> (+5.14%) ⬆️
instrumentations-bucket-12 52.67% <100.00%> (-0.28%) ⬇️
instrumentations-bucket-13 52.71% <100.00%> (+0.20%) ⬆️
instrumentations-bucket-2 54.01% <100.00%> (-0.03%) ⬇️
instrumentations-bucket-3 54.31% <100.00%> (-0.03%) ⬇️
instrumentations-bucket-4 60.06% <100.00%> (-0.03%) ⬇️
instrumentations-bucket-5 50.58% <100.00%> (-0.02%) ⬇️
instrumentations-bucket-6 61.86% <100.00%> (-0.03%) ⬇️
instrumentations-bucket-7 59.20% <100.00%> (-0.03%) ⬇️
instrumentations-bucket-8 60.27% <100.00%> (-0.03%) ⬇️
instrumentations-bucket-9 52.47% <52.20%> (-10.01%) ⬇️
instrumentations-instrumentation-couchbase 51.97% <100.00%> (-0.03%) ⬇️
instrumentations-instrumentation-zlib 52.35% <100.00%> (?)
instrumentations-integration-esbuild 34.18% <60.33%> (+0.13%) ⬆️
llmobs-ai_anthropic_bedrock 63.37% <65.06%> (-0.02%) ⬇️
llmobs-bucket-1 62.60% <100.00%> (-0.02%) ⬇️
llmobs-openai 63.32% <100.00%> (-0.02%) ⬇️
llmobs-sdk 65.44% <100.00%> (-0.03%) ⬇️
llmobs-vertex-ai 60.01% <100.00%> (-0.03%) ⬇️
master-coverage 98.43% <100.00%> (?)
openfeature 54.68% <47.59%> (-0.04%) ⬇️
openfeature-unit 53.45% <48.03%> (-0.07%) ⬇️
platform-core_esbuild_instrumentations-misc 40.97% <60.33%> (+0.29%) ⬆️
platform-integration 62.56% <92.09%> (+0.23%) ⬆️
platform-shimmer_unit-guardrails_webpack 39.47% <64.79%> (+0.11%) ⬆️
plugins-bucket-0 57.79% <100.00%> (-0.02%) ⬇️
plugins-bucket-1 55.21% <100.00%> (+<0.01%) ⬆️
plugins-bucket-11 63.12% <100.00%> (-0.02%) ⬇️
plugins-bucket-18 62.91% <59.43%> (-0.05%) ⬇️
plugins-bucket-19 60.99% <100.00%> (-0.03%) ⬇️
plugins-bucket-20 62.93% <100.00%> (-0.03%) ⬇️
plugins-bucket-4 59.43% <100.00%> (-0.03%) ⬇️
plugins-bullmq_cassandra_cookie 62.71% <100.00%> (-0.03%) ⬇️
plugins-cookie-parser_crypto_dd-trace-api 57.61% <100.00%> (-0.03%) ⬇️
plugins-fetch_fs_generic-pool 59.71% <100.00%> (+0.02%) ⬆️
plugins-google-cloud-pubsub_grpc_handlebars 65.69% <65.06%> (-0.03%) ⬇️
plugins-hapi_hono_ioredis 61.14% <100.00%> (-0.03%) ⬇️
plugins-jest_knex_langgraph 56.41% <100.00%> (-0.03%) ⬇️
plugins-ldapjs_light-my-request_limitd-client 59.40% <100.00%> (-0.03%) ⬇️
plugins-lodash_mariadb_memcached 58.89% <100.00%> (-0.03%) ⬇️
plugins-moleculer_mongodb_mongodb-core 62.87% <100.00%> (-0.03%) ⬇️
plugins-mongoose_multer_mysql 59.89% <100.00%> (-0.03%) ⬇️
plugins-mysql2_nats_node-serialize 61.67% <100.00%> (-0.03%) ⬇️
plugins-opensearch_passport-http_pino 60.45% <100.00%> (-0.03%) ⬇️
plugins-postgres_process_pug 59.17% <100.00%> (-0.03%) ⬇️
plugins-redis_router_sequelize 63.01% <100.00%> (-0.03%) ⬇️
plugins-test-and-upstream-rhea_undici_url 62.57% <100.00%> (-0.03%) ⬇️
plugins-valkey_vm_winston 58.87% <100.00%> (-0.03%) ⬇️
plugins-ws 60.50% <100.00%> (-0.03%) ⬇️
profiling 63.10% <100.00%> (-0.03%) ⬇️
serverless-aws-sdk-aws-sdk 55.75% <100.00%> (-0.02%) ⬇️
serverless-aws-sdk-bedrockruntime 55.47% <100.00%> (-0.02%) ⬇️
serverless-aws-sdk-client 57.21% <100.00%> (-0.03%) ⬇️
serverless-aws-sdk-dynamodb 56.40% <100.00%> (-0.02%) ⬇️
serverless-aws-sdk-eventbridge 49.98% <100.00%> (-0.02%) ⬇️
serverless-aws-sdk-kinesis 60.18% <100.00%> (-0.02%) ⬇️
serverless-aws-sdk-lambda 58.17% <100.00%> (-0.02%) ⬇️
serverless-aws-sdk-s3 56.34% <100.00%> (-0.02%) ⬇️
serverless-aws-sdk-serverless-peer-service 60.60% <100.00%> (-0.02%) ⬇️
serverless-aws-sdk-sns 61.00% <100.00%> (-0.02%) ⬇️
serverless-aws-sdk-sqs 61.43% <100.00%> (-0.06%) ⬇️
serverless-aws-sdk-stepfunctions ?
serverless-aws-sdk-util 52.25% <100.00%> (-0.03%) ⬇️
serverless-bucket-0 58.84% <62.65%> (+3.59%) ⬆️
serverless-bucket-1 54.65% <100.00%> (-5.50%) ⬇️
serverless-lambda 56.85% <100.00%> (?)
test-optimization-cucumber 72.71% <100.00%> (-0.02%) ⬇️
test-optimization-cypress 66.12% <65.06%> (+0.10%) ⬆️
test-optimization-jest 74.18% <100.00%> (+0.02%) ⬆️
test-optimization-mocha 74.43% <100.00%> (+0.06%) ⬆️
test-optimization-playwright-playwright-atr 61.14% <100.00%> (+0.02%) ⬆️
test-optimization-playwright-playwright-efd 61.34% <100.00%> (+0.03%) ⬆️
test-optimization-playwright-playwright-final-status 61.31% <100.00%> (+0.02%) ⬆️
test-optimization-playwright-playwright-impacted-tests 61.03% <100.00%> (+0.19%) ⬆️
test-optimization-playwright-playwright-reporting 60.93% <100.00%> (+0.02%) ⬆️
test-optimization-playwright-playwright-test-management 61.64% <100.00%> (-0.31%) ⬇️
test-optimization-playwright-playwright-test-span 61.06% <100.00%> (-0.03%) ⬇️
test-optimization-selenium 60.48% <100.00%> (-0.13%) ⬇️
test-optimization-testopt 59.02% <100.00%> (+0.08%) ⬆️
test-optimization-vitest 71.02% <100.00%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread packages/dd-trace/src/config/index.js Outdated
BridgeAR added a commit that referenced this pull request Jun 26, 2026
The guard that disables DD_LOGS_OTEL_ENABLED and DD_METRICS_OTEL_ENABLED when
@opentelemetry/api is absent warned unconditionally. If a later release defaults
one of these flags on, every app without the optional peer would get a warning
for a feature it never opted into. Warn only when the flag's origin is the
customer (tracked in trackedConfigOrigins); disable a default-on flag silently.

The config test harness gains a defaultsOverride hook so the default-on path runs
through the real #applyDefaults (which sets defaults untracked) instead of poking
internal state.

Refs: #9077 (comment)
@BridgeAR
BridgeAR force-pushed the BridgeAR/2026-06-26-otel-api-optional-peer branch from 7ae51db to b375026 Compare June 26, 2026 13:49
@BridgeAR
BridgeAR marked this pull request as ready for review June 26, 2026 14:42
@BridgeAR
BridgeAR requested review from a team as code owners June 26, 2026 14:42
@BridgeAR
BridgeAR requested review from khanayan123, leoromanovsky, mabdinur, typotter and zacharycmontoya and removed request for a team June 26, 2026 14:42

@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: b3750262a7

ℹ️ 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 packages/dd-trace/src/opentelemetry/api.js Outdated
mabdinur
mabdinur previously approved these changes Jun 26, 2026
Comment thread packages/dd-trace/src/opentelemetry/api.js
Comment thread packages/dd-trace/src/opentelemetry/api.js Outdated
Comment thread package.json Outdated

@zacharycmontoya zacharycmontoya left a comment

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.

While I am not an expert on the Node.js require mechanism, at a high-level the loading logic and the unit tests look good to me. I'd appreciate a review from someone more knowledgeable about Node.js on this

@zacharycmontoya zacharycmontoya left a comment

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.

LGTM again after the changes to also handle the @opentelemetry/api-logs package

@BridgeAR
BridgeAR requested review from a team as code owners June 26, 2026 20:29
@BridgeAR
BridgeAR removed the request for review from a team June 26, 2026 20:29
@BridgeAR
BridgeAR marked this pull request as draft July 2, 2026 14:58
@BridgeAR
BridgeAR dismissed stale reviews from dd-oleksii and mabdinur via 9f94958 July 2, 2026 17:27
@BridgeAR
BridgeAR force-pushed the BridgeAR/2026-06-26-otel-api-optional-peer branch 2 times, most recently from 9f94958 to f4810d7 Compare July 7, 2026 18:42
@leoromanovsky
leoromanovsky requested review from greghuels and removed request for leoromanovsky July 7, 2026 19:46
greghuels
greghuels previously approved these changes Jul 7, 2026
@BridgeAR
BridgeAR force-pushed the BridgeAR/2026-06-26-otel-api-optional-peer branch 5 times, most recently from 40f4a78 to 5f8c7b4 Compare July 16, 2026 02:57
BridgeAR added 14 commits July 20, 2026 14:39
…ridge

dd-trace bundles its own @opentelemetry/api as an optional dependency. The OTel
global API keys providers per major and rejects one registered by a copy older
than the reader's, so once the application loaded a newer copy the bridge's
provider lost the version check and every span silently downgraded to a no-op
(reported with @opentelemetry/api >1.4.1).

An instrumentation now captures the application's own copy of @opentelemetry/api
and @opentelemetry/api-logs the moment the application requires it, and every
trace, metrics, and logs module reads that copy through a holder. When the
application ships its own copy the bridge registers on it and the version
mismatch disappears; when it does not, the holder falls back to the bundled
copy, so nothing outside dd-trace reads OTel and the single bundled copy has
nothing to clash with. The trace bridge and the OTLP metrics and logs pipelines
therefore keep working without the application adding the packages itself, and
they initialize eagerly again rather than waiting on the capture.

The @opentelemetry/api-logs hook is scoped to >=0.33.0 <1.0.0: the package has
no 1.0.0 release, and an open-below <1.0.0 range makes the plugin version matrix
coerce a non-existent 1.0.0 floor and fail to install.

Fixes: #6882
…bundling

The bridge binds to the application's @opentelemetry/api copy through an
instrumentation that fires on a runtime require. A bundler resolves a
string-literal require at build time, so bundling the API packages inlines a
second copy the instrumentation never sees; the bridge then registers its
provider on the wrong copy and downgrades every span to a no-op. Marking
@opentelemetry/api and @opentelemetry/api-logs external keeps the require intact
for interception. The webpack `commonjs` external type forces a CommonJS require
regardless of the user's externalsType.

Fixes: #6882
Bridge modules read the captured @opentelemetry/api copy at module load. The
application's copy is captured when it requires the package, which can happen
after a bridge module has already loaded, so the module kept dd-trace's fallback
copy. Registering the provider on that copy while the application reads its own
lets the OpenTelemetry global API reject the older registration and downgrade
every span to a no-op (issue #6882).

Every copy-sensitive path now reads the API through the holder at use time:
provider registration, context conversion, span creation, log emission, and
runtime metrics. A copy captured after the module loaded is therefore the one the
bridge registers on and uses. SpanKind and SeverityNumber stay resolved at load
because they are spec-fixed constants, identical across copies.

Fixes: #6882
…app has no copy

The plugins marked @opentelemetry/api and @opentelemetry/api-logs external
unconditionally, so a bundle that used the OpenTelemetry bridge but was deployed
without the packages in node_modules threw at runtime on the fallback require.
Externalizing is only needed when the application owns a copy the instrumentation
must capture and share; a package the application does not declare has no
competing copy to protect.

Externalize a package only when the application's package.json declares it, and
otherwise leave it in the bundle so dd-trace's own copy is inlined and the bundle
stays self-contained. When the manifest cannot be read, keep externalizing so the
shared-copy correctness is never traded for the self-contained-bundle
optimization.

Fixes: #6882
An API subpath or dd-trace's fallback can load before the application's package entrypoint. Treating that first hook as authoritative leaves provider registration on the wrong OpenTelemetry global registry, and ESM namespaces cannot be patched in place.

Prefer the API resolved from the application entrypoint, keep fallback loads out of capture, and resolve the holder at each use so late CommonJS and ESM loads share the application's registry. Bundlers only externalize application-owned API packages, preserving self-contained fallback bundles.

Fixes: #6882
An application-owned OpenTelemetry API can load after dd-trace has already registered providers against its fallback. Keeping those registrations on the fallback registry leaves the application's trace, metrics, and logs calls as silent no-ops.

Track capture ownership and priority, move registrations atomically when a better application copy appears, and bind hot paths directly to the selected API. Resolve only supported installed application dependencies, preserve required bundler external precedence, and cover relocated CJS and ESM bundles with real API copies.

Fixes: #6882
Patch coverage exposed untested branches around generated ownership metadata, missing request values, empty trace state, and repeated provider registration. Pin those boundaries so regressions cannot silently change which OpenTelemetry registry receives providers.
OpenTelemetry keeps its original global version after disable(), so transferring providers to a later API copy can reject the next registration and leave supported application copies on no-op providers. Keep provider registration on pinned compatibility-max owners; late captures only replace immutable copy-local snapshots.

Resolve API ownership from each workspace importer so nested applications externalize their declared runtime copy without externalizing dd-trace's fallback.

Fixes: #6882
An older API can claim OpenTelemetry's core global by configuring diagnostics, causing later provider registration through the pinned copy to fail its exact-version check. Replacing only that diagnostic-only owner preserves the logger and lets the pinned compatibility-max copy own every signal without moving live providers.

Relocated bundles keep dd-trace's fallback graph internal, while application API imports still honor user externals.
Regular dependencies let dd-trace's resolver win over an application-owned copy, which can leave bridge operations on a different global registry. Keep the fallback copies optional. Provider registration remains pinned to compatibility-max owners.

Fixes: #6882
Bun 1.3.1 strips scopes from npm aliases while importing Yarn v1 locks, making CI request nonexistent unscoped packages.

Refs: oven-sh/bun#27781
Bun's Yarn v1 lockfile migration drops scopes from npm alias targets, making every CI install request nonexistent unscoped packages.

Refs: oven-sh/bun#27781
The package-size job resolves dev dependencies from the packed manifest even under --prod, where local test fixture paths do not exist.
Windows treats drive-letter loader paths as URL schemes and resolves rooted paths against the current drive. Use URL and absolute-path forms that preserve the fixture intent on every platform.
@BridgeAR
BridgeAR force-pushed the BridgeAR/2026-06-26-otel-api-optional-peer branch from 5cc58e0 to e1c972a Compare July 20, 2026 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: @opentelemetry/api version compatibility issue: TracerProvider produces no-op spans with versions >1.4.1

6 participants