Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions reference/configuration/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,27 +65,29 @@ threads:
- `maxHeapMemory` — Heap limit per thread (MB)
- `heapSnapshotNearLimit` — Write a `.heapsnapshot` file when a thread nears its heap limit (loadable in Chrome DevTools Memory tab); _Default_: `false`. See [Worker Thread Debugging](./debugging.md#heap-snapshots-near-the-limit)
- `debug` — Enable Node.js inspector; sub-options: `port`, `startingPort`, `host`, `waitForDebugger`. See [Worker Thread Debugging](./debugging.md)
- `preload` <VersionBadge version="v5.2.0" /> — Module, or list of modules, to load (via Node's `--import`) before any Harper or application module on each worker thread. Intended for instrumentation/APM agents that must load first to instrument subsequent module loads. Use the agent's ESM/register entry — e.g. `dd-trace/register.js`, which registers the loader hooks that instrument worker threads (where Harper runs its work); the plain `dd-trace/init` (`--require`) entry only covers the main thread. Bare specifiers resolve against the `node_modules` of your installed [components](../components/overview.md) — so the agent can be shipped as a dependency of a deployed component — and absolute paths are also accepted. Applies to worker threads only (not under Bun).
- `preload` <VersionBadge version="v5.2.0" /> — Module, or list of modules, to load (via Node's `--import`) before any Harper or application module on each worker thread. Intended for instrumentation/APM agents that must load first to instrument subsequent module loads. Use the agent's ESM/register entry — e.g. `dd-trace/register.js`, which installs the ESM loader hooks that produce automatic instrumentation for `import`-loaded modules. As measured on dd-trace 6.x, that entry only registers the loader hooks and never calls `init()`, so `preload` on its own leaves the tracer uninitialized: it still hands out spans with plausible trace ids, but they are no-ops and nothing is ever exported. Pair it with `preloadRequire: dd-trace/init`, which is the entry that actually starts the tracer. `dd-trace/initialize.mjs` is not a single-entry shortcut around this pairing: it gates both its `init()` call and its loader-hook registration behind `isMainThread`, so under `--import` on a worker thread it starts nothing and registers nothing. Bare specifiers resolve against the `node_modules` of your installed [components](../components/overview.md) — so the agent can be shipped as a dependency of a deployed component — and absolute paths are also accepted. Applies to worker threads only (not under Bun).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could we confirm this as an end-to-end Harper worker setup before documenting it as the dd-trace recipe? register.js installing loader hooks and init starting the tracer does not establish that Harper's actual worker execArgv composition produces exported spans with usable context and shutdown behavior. Please add a reproducible Harper validation (for example, a component emitting a known trace to a test agent) and summarize or link its scope/result; otherwise keep this guidance agent-neutral and describe dd-trace as unverified.


```yaml
threads:
preload: dd-trace/register.js
preloadRequire: dd-trace/init # starts the tracer
preload: dd-trace/register.js # ESM loader hooks for automatic instrumentation
```

Or several modules:
Or several modules. The `preloadRequire` pairing still applies — an agent listed here is subject to the same rule as when it is the only entry:

```yaml
threads:
preloadRequire: dd-trace/init # still what starts the tracer
preload:
- dd-trace/register.js
- /opt/instrumentation/agent.mjs

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This still presents a directly copyable dd-trace configuration with only preload, but the new text establishes that dd-trace/register.js does not call init(). Adding an instrumentation module to this example therefore leaves each worker's tracer uninitialized and exports no traces—the silent failure this PR is fixing. Add preloadRequire: dd-trace/init to this example too (or use dd-trace/initialize.mjs as the single preload) so every shown dd-trace configuration is viable.

(reference/configuration/options.md:81 is not part of this PR's diff — anchored to the nearest line this PR's diff can hold)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch — fixed. The multi-module example now carries preloadRequire: dd-trace/init alongside the preload list, so every dd-trace configuration shown on the page is viable.

I did chase down initialize.mjs, and it is not the simpler single entry it looks like: on 6.x it gates both its init() call and its Module.register('./loader-hook.mjs') behind isMainThread, and its exported load/resolve hooks only take effect when the file is passed to --loader. Since we preload with --import in the worker's execArgv, that means it starts nothing and registers nothing on a worker thread — I confirmed it on dd-trace 6.12.0 / Node 24.19.0, where the worker's tracer stays a NoopTracer, i.e. the same silent failure as register.js alone, minus the loader hooks.

So I've stuck with the two-key pairing and added a line to the preload bullet recording why initialize.mjs isn't a shortcut around it, so the next person doesn't reach for it either.

sent with Claude Opus 5

```

- `preloadRequire` <VersionBadge version="v5.2.0" /> — Same as `preload`, but loads modules via Node's `--require` (CommonJS) instead of `--import`. Use this for agents that document the `--require` path and do not need ESM loader hooks (e.g. `dd-trace/init`, Dynatrace OneAgent). Same resolution rules as `preload`.
- `preloadRequire` <VersionBadge version="v5.2.0" /> — Same as `preload`, but loads modules via Node's `--require` (CommonJS) instead of `--import`. Use this for agents that document the `--require` path (e.g. `dd-trace/init`, Dynatrace OneAgent). Same resolution rules as `preload`. For dd-trace, `dd-trace/init` is the entry that starts the tracer, and it does not register the ESM loader hooks — keep `preload: dd-trace/register.js` alongside it, as shown under `preload` above.

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.

medium

According to the general rules, we should use hyphens (-) instead of em dashes () as field separators (e.g., separating configuration option names from their descriptions) in Markdown documentation. Additionally, the <VersionBadge> component should be reserved for standalone placement after headings; for inline version annotations inside list items, plain text like (v5.2.0) should be used instead.

Suggested change
- `preloadRequire` <VersionBadge version="v5.2.0" /> — Same as `preload`, but loads modules via Node's `--require` (CommonJS) instead of `--import`. Use this for agents that document the `--require` path (e.g. `dd-trace/init`, Dynatrace OneAgent). Same resolution rules as `preload`. For dd-trace, `dd-trace/init` is the entry that starts the tracer, and it does not register the ESM loader hooks — keep `preload: dd-trace/register.js` alongside it, as shown under `preload` above.
- `preloadRequire` (v5.2.0) - Same as `preload`, but loads modules via Node's `--require` (CommonJS) instead of `--import`. Use this for agents that document the `--require` path (e.g. `dd-trace/init`, Dynatrace OneAgent). Same resolution rules as `preload`. For dd-trace, `dd-trace/init` is the entry that starts the tracer, and it does not register the ESM loader hooks — keep `preload: dd-trace/register.js` alongside it, as shown under `preload` above.
References
  1. In Markdown documentation, use hyphens ('-') instead of em dashes ('—') as field separators (e.g., separating configuration option names from their descriptions) to adhere to the style guide, even if the file has pre-existing inconsistencies using em dashes.
  2. Reserve the component for standalone placement after headings. For inline version annotations mid-sentence or inside list items, use plain text (e.g., (vX.Y.Z)) instead, as using the component mid-sentence is awkward.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Not taking this one. The em-dash rule is being over-generalized here.

AGENTS.md says em dashes "are fine for parenthetical asides and match existing prose; do not use them as field separators." The field-separator prohibition refers to the bullet immediately above it - Type: / Default: reference blocks, where each field goes on its own line. It is not a ban on - **term** — description in prose lists.

Two checks: the docs tree has 633 em-dash list-item lines across 63 reference files, and AGENTS.md itself uses this exact pattern - including in the rule being quoted (- **Hyphens vs. dashes** — em dashes...).

So these are the established convention, not "pre-existing inconsistencies." Applying the suggestion would leave the touched lines inconsistent with every sibling line in the same list.

sent with Claude Opus 5


```yaml
threads:
preloadRequire: dd-trace/init
preloadRequire: dd-trace/init # starts the tracer; pair with preload (see above)
```

---
Expand Down