Skip to content

support ddtrace v6 for node > 22 - #818

Open
ojproductions wants to merge 2 commits into
mainfrom
onzia/moreddtrace6
Open

support ddtrace v6 for node > 22#818
ojproductions wants to merge 2 commits into
mainfrom
onzia/moreddtrace6

Conversation

@ojproductions

Copy link
Copy Markdown
Contributor

What does this PR do?

Motivation

Testing Guidelines

Additional Notes

Types of Changes

  • Bug fix
  • New feature
  • Breaking change
  • Misc (docs, refactoring, dependency upgrade, etc.)

Check all that apply

  • This PR's description is comprehensive
  • This PR contains breaking changes that are documented in the description
  • This PR introduces new APIs or parameters that are documented and unlikely to change in the foreseeable future
  • This PR impacts documentation, and it has been updated (or a ticket has been logged)
  • This PR's changes are covered by the automated tests
  • This PR collects user input/sensitive content into Datadog
  • This PR passes the integration tests (ask a Datadog member to run the tests)

@ojproductions
ojproductions requested review from a team as code owners August 27, 2026 15:12
@ojproductions
ojproductions requested a review from lym953 August 27, 2026 15:12
@datadog-datadog-prod-us1

This comment has been minimized.

@joeyzhao2018

Copy link
Copy Markdown
Contributor

Thanks for working on the per-runtime tracer split. The layer mapping (v5 for Node 18/20 and v6 for Node 22+) makes sense. I think the npm contract needs to be explicit before we rely on this for the migration. Here are concrete changes I suggest:

1. Declare the npm compatibility contract

dd-trace is still a devDependency, so changing it to v6 does not control what npm consumers install. Since the current code intentionally lets customers bring their own tracer, I suggest adding an engine and an optional peer range:

{
  "engines": {
    "node": ">=18"
  },
  "peerDependencies": {
    "dd-trace": "^5.123.0 || ^6.12.0"
  },
  "peerDependenciesMeta": {
    "dd-trace": {
      "optional": true
    }
  }
}

The root devDependency can remain ^6.12.0 for repository development. The optional peer prevents npm from automatically choosing v6 when no tracer is installed. We should also document Node 18/20 -> v5 and Node 22+ -> v6.

2. Keep v6 out of the shared npm package's runtime dependencies

The published npm manifest should not contain:

"dependencies": {
  "dd-trace": "^6.12.0"
}

Instead, only generated layer manifests should receive an exact, runtime-specific dependency. For example, move_ddtrace_dependency.js could accept the resolved version:

const file = JSON.parse(process.argv[2])
const ddTraceVersion = process.argv[3]

if (!ddTraceVersion) throw new Error('A resolved dd-trace version is required')

delete file.devDependencies['dd-trace']
file.dependencies['dd-trace'] = ddTraceVersion

Called with:

resolved_dd_trace_version=$(node -p "require('dd-trace/package.json').version")
node scripts/move_ddtrace_dependency.js \
  "$(cat package.json)" \
  "$resolved_dd_trace_version" > package-new.json

3. Test the actual packed npm artifact

The container fixtures manually choose v5/v6, which proves the code works with the chosen tracer but does not test the npm package contract. I suggest building one tarball on Node 22, then installing that same tarball in a matrix:

strategy:
  matrix:
    include:
      - { node: 18, dd_trace: 5.123.0 }
      - { node: 20, dd_trace: 5.123.0 }
      - { node: 22, dd_trace: 6.12.0 }
      - { node: 24, dd_trace: 6.12.0 }
      - { node: 26, dd_trace: 6.12.0 }

Each leg should create an empty app and install the packed artifact plus the selected tracer:

npm init -y
npm install "dd-trace@$DD_TRACE_VERSION"
npm install ../datadog-lambda-js.tgz
node -e "require('datadog-lambda-js'); console.log(require('dd-trace/package.json').version)"

If metrics-only operation without a tracer remains supported, please add a tarball test with no dd-trace installed as well.

4. Report the tracer version loaded at runtime

The npm publish job currently builds with v6 and stamps that into dist/trace/constants.js. A Node 18 customer bringing v5 would therefore report v6. TracerWrapper already resolves the customer's tracer, so it can resolve the matching package metadata too:

private loadedTracerVersion = ''

const paths = ['/var/task/node_modules', ...module.paths]
const tracerPath = require.resolve('dd-trace', { paths })
this.tracer = require(tracerPath)
const packagePath = require.resolve('dd-trace/package.json', { paths })
this.loadedTracerVersion = require(packagePath).version

public get tracerVersion(): string {
  return this.loadedTracerVersion
}

Then use:

dd_trace: this.tracerWrapper.tracerVersion

instead of the build-time ddtraceVersion constant.

5. Avoid leaving tracked manifests modified

For Node 18/20, install_deps.sh currently rewrites package.json and may rewrite yarn.lock. Please perform the override against temporary copies and restore both files:

package_backup=$(mktemp)
lock_backup=$(mktemp)
cp package.json "$package_backup"
cp yarn.lock "$lock_backup"

restore_manifests() {
  cp "$package_backup" package.json
  cp "$lock_backup" yarn.lock
  rm -f "$package_backup" "$lock_backup"
}
trap restore_manifests EXIT

The installed tracer version can still be read from node_modules/dd-trace/package.json and passed to the layer-manifest step described above.

6. Add a release check for the manually maintained v5 pin

DD_TRACE_V5_VERSION is separate from package.json and will not be updated by the existing dependency-update workflow. A release check could fail when it is stale:

source ./scripts/dd_trace_versions.sh
latest_v5=$(npm view 'dd-trace@5' version --json | jq -r 'if type == "array" then last else . end')

if [ "$DD_TRACE_V5_VERSION" != "$latest_v5" ]; then
  echo "dd-trace v5 pin is stale: configured=$DD_TRACE_V5_VERSION latest=$latest_v5"
  exit 1
fi

The main distinction is that the layer split is runtime-controlled, while an npm devDependency does not define customer resolution. These changes would preserve Node 18/20 npm support and make that contract testable.

Comment thread migration_parity.md
| No post-Node-18 syntax on the plugin path | dd:`packages/datadog-plugin-lambda/**` | L1 (dd-trace-js lint) | lint rule pinned to Node 18 target — new | pending | dd-trace |
| Config wiring applied per-line (`config/index.js` is not cherry-pick-clean) | dd:`packages/dd-trace/src/config/index.js` × 2 lines | L1 (dd-trace-js) | config spec on both lines | pending | dd-trace |
| npm range resolves to v5 on Node 18 | shim:`package.json` | L1 (datadog-lambda-js) | install test on Node 18 — new | pending | both |
| dd-trace resolves to v5 on Node 18 (`package.json` carries the v6 line) | shim:`scripts/install_deps.sh` + `scripts/dd_trace_versions.sh` | L1 (datadog-lambda-js) | install test on Node 18 — new | ported | both |

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.

Suggested change
| dd-trace resolves to v5 on Node 18 (`package.json` carries the v6 line) | shim:`scripts/install_deps.sh` + `scripts/dd_trace_versions.sh` | L1 (datadog-lambda-js) | install test on Node 18 — new | ported | both |
| npm package works on Node 18/20 with customer-installed dd-trace v5 | shim:`package.json` + packed npm artifact | L1 (datadog-lambda-js) | packed-tarball install test on Node 18 and 20 — new | pending | both |

To be more precise, keeping it pending here because install_deps.sh only implements build/layer selection, it does not establish or test npm customer resolution yet...

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.

2 participants