-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
What happened?
The _httpPatched / _httpsPatched guards added in #6437 prevent IITM from patching the ESM proxy for http/https when RITM has already patched them via CJS. This breaks outgoing HTTP span instrumentation for ESM code in environments where the IITM proxy snapshots stale (unpatched) exports—most notably AWS Lambda.
Steps to Reproduce
https://github.com/andreiborza/otel-http-esm-guard-repro
There are three npm scripts demonstrating the issue:
# 0.213.0 — FAIL (no client span)
npm run start:213
# 0.212.0 — PASS (client span created)
npm run start:212
# 0.213.0 with proposed fix — PASS (ESM span created + CJS no double spans)
npm run start:213-patchedExpected Result
Getting http spans for outgoing requests.
Actual Result
Not getting http spans for outgoing requests.
Additional Details
In AWS Lambda with an ESM handler:
--import ./setup.mjsruns—staticimport 'node:http'pre-caches the ESM namespace with unpatched CJS exports- Lambda runtime (CJS) requires
node:http—RITM fires, patches the CJS module, sets_httpPatched = true - Lambda runtime imports the ESM handler—handler does
import * as http from 'node:http' - IITM intercepts, creates a proxy wrapping
node:http—but the cached ESM namespace has unpatched snapshot values - IITM calls the HttpInstrumentation hook—
_httpPatchedistrue→ early return → proxy is not patched - Handler's
http.request(...)uses the unpatched snapshot → no client span
The Lambda runtime's RAPIDClient loads http via cjsRequire("node:http"), which goes through Module.prototype.require and triggers RITM.
Suggested fix
Replace the boolean flag with an object identity check:
// Current (breaks ESM when proxy has stale snapshots):
if (this._httpPatched) { return moduleExports; }
this._httpPatched = true;// Proposed (skips only if it's the exact same object):
if (this._httpPatchedExports === moduleExports) { return moduleExports; }
this._httpPatchedExports = moduleExports;This preserves the double-span fix from #6428 (same object → skip) while allowing IITM to patch a different proxy object
independently.
The reproduction repo includes a patch file with this fix and npm run start:213-patched tests both:
- ESM handler: confirms client span is created (fix works)
- CJS handler: confirms exactly 1 client span, no double spans (no regression of [instrumentation-http] double instrumentation if IITM loader is registered #6428
Tip
React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.