reference/configuration/options.md:68 says, in the threads.preload entry:
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.
and the standalone example at :70-73 reinforces it:
threads:
preload: dd-trace/register.js
A reader following this configures preload: dd-trace/register.js, restarts, and gets zero
telemetry with no error anywhere. Measured on dd-trace 6.10.0 under Harper 5.2, same endpoint,
three configurations, against a live trace receiver on 8126:
| Worker flags |
tracerInitialized |
Spans received |
| neither |
false |
none |
--import dd-trace/register.js only (threads.preload) |
false |
none |
--require dd-trace/init (threads.preloadRequire) |
true |
all four |
(The table and its measurement context are recorded in the datadog-agent-binary example:
example/README.md:101-113 at commit bbeb99a.)
The mechanism, verified against the dd-trace 6.10.0 sources: dd-trace/register.js installs
ESM loader hooks and never calls init(); dd-trace/init is a CommonJS module whose body
calls require('dd-trace').init(), which is what actually starts the tracer. The failure is
invisible by construction: an uninitialised dd-trace still runs tracer.trace() callbacks and
hands out spans whose context().toTraceId() returns plausible ids; they are NoopSpans and
nothing is ever sent.
The doc's claim reads as a general fact about dd-trace; the measured behavior says the two
entries do different jobs and neither substitutes for the other. preloadRequire: dd-trace/init
starts the tracer; preload: dd-trace/register.js adds the ESM loader hooks that produce
automatic http spans for import-loaded modules.
Suggested edit, scoped to what was measured rather than stated as a timeless fact:
- In the
preload bullet, replace "the plain dd-trace/init (--require) entry only covers
the main thread" with an explicit statement that register.js never calls init(), so
preload alone produces an initialised-looking but inert tracer; label the behavior as
measured on dd-trace 6.x (a future dd-trace major could change register.js).
- Make the dd-trace example show both keys together:
threads:
preloadRequire: dd-trace/init # starts the tracer
preload: dd-trace/register.js # ESM loader hooks for automatic instrumentation
- Cross-reference the two bullets so a reader who lands on either sees the pairing.
Reproduction
- Harper 5.2.1, a component using dd-trace 6.10.0, a listener on 127.0.0.1:8126.
- Set only
threads.preload: dd-trace/register.js in harperdb-config.yaml; restart.
- Hit an instrumented endpoint. Observed: the response carries a plausible trace id while the
tracer reports uninitialised (tracer._tracer._exporter absent /
tracerInitialized: false in the example app) and the trace-agent's periodic summary stays
at traces received: 0.
- Add
threads.preloadRequire: dd-trace/init; restart. Observed: tracer initialised, spans
arrive (traces received climbs).
The datadog-agent-binary example automates steps 3-4: example/resources.js reports
tracerInitialized on GET /Work/ and its README documents the same repro
(example/README.md:101-113, :334).
Measured on
| Component |
Version |
| Harper |
5.2.1 |
| dd-trace |
6.10.0 |
| Node |
v24.16.0 |
| OS |
macOS 26.5.2 (arm64, Darwin 25.5.0) |
| documentation repo |
d4cbc1a7 (reference/configuration/options.md:68-91) |
| evidence checkout |
datadog-agent-binary bbeb99a (example/README.md, example/harper-config.yaml) |
reference/configuration/options.md:68says, in thethreads.preloadentry:and the standalone example at
:70-73reinforces it:A reader following this configures
preload: dd-trace/register.js, restarts, and gets zerotelemetry with no error anywhere. Measured on dd-trace 6.10.0 under Harper 5.2, same endpoint,
three configurations, against a live trace receiver on 8126:
tracerInitializedfalse--import dd-trace/register.jsonly (threads.preload)false--require dd-trace/init(threads.preloadRequire)true(The table and its measurement context are recorded in the datadog-agent-binary example:
example/README.md:101-113at commitbbeb99a.)The mechanism, verified against the dd-trace 6.10.0 sources:
dd-trace/register.jsinstallsESM loader hooks and never calls
init();dd-trace/initis a CommonJS module whose bodycalls
require('dd-trace').init(), which is what actually starts the tracer. The failure isinvisible by construction: an uninitialised dd-trace still runs
tracer.trace()callbacks andhands out spans whose
context().toTraceId()returns plausible ids; they areNoopSpans andnothing is ever sent.
The doc's claim reads as a general fact about dd-trace; the measured behavior says the two
entries do different jobs and neither substitutes for the other.
preloadRequire: dd-trace/initstarts the tracer;
preload: dd-trace/register.jsadds the ESM loader hooks that produceautomatic
httpspans forimport-loaded modules.Suggested edit, scoped to what was measured rather than stated as a timeless fact:
preloadbullet, replace "the plaindd-trace/init(--require) entry only coversthe main thread" with an explicit statement that
register.jsnever callsinit(), sopreloadalone produces an initialised-looking but inert tracer; label the behavior asmeasured on dd-trace 6.x (a future dd-trace major could change
register.js).Reproduction
threads.preload: dd-trace/register.jsinharperdb-config.yaml; restart.tracer reports uninitialised (
tracer._tracer._exporterabsent /tracerInitialized: falsein the example app) and the trace-agent's periodic summary staysat
traces received: 0.threads.preloadRequire: dd-trace/init; restart. Observed: tracer initialised, spansarrive (
traces receivedclimbs).The datadog-agent-binary example automates steps 3-4:
example/resources.jsreportstracerInitializedonGET /Work/and its README documents the same repro(
example/README.md:101-113,:334).Measured on
d4cbc1a7(reference/configuration/options.md:68-91)bbeb99a(example/README.md,example/harper-config.yaml)