-
Notifications
You must be signed in to change notification settings - Fork 983
fix(instrumentation-http): Ensure instrumentation of http.get and https.get work when used in ESM code
#4866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…https.get` work when used in ESM code The issue was that the `_wrap`ing of `http.get` was getting the just-wrapped `http.request` by accessing `moduleExports.request`. However, when wrapping an ES module the `moduleExports` object from IITM is a Proxy object that allows setting a property, but *not* re-getting that set property. The fix is to use the wrapped `http.request` from the `this._wrap` call. That required fixing a bug in the IITM code-path of `InstrumentationBase.prototype._wrap` to return the wrapped property. (The previous code was doing `return Object.defineProperty(...)`, which returns the moduleExports, not the defined property.) Fixes: open-telemetry#4857
experimental/packages/opentelemetry-instrumentation-http/test/integrations/esm.test.mjs
Fixed
Show fixed
Hide fixed
experimental/packages/opentelemetry-instrumentation-http/test/integrations/esm.test.mjs
Fixed
Show fixed
Hide fixed
| "test": "nyc mocha test/**/*.test.ts", | ||
| "test:cjs": "nyc mocha test/**/*.test.ts", | ||
| "test:esm": "nyc node --experimental-loader=@opentelemetry/instrumentation/hook.mjs ../../../node_modules/.bin/mocha 'test/**/*.test.mjs'", | ||
| "test": "npm run test:cjs && npm run test:esm", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewer note: This test:esm script follows the same pattern used for ESM tests in opentelemetry-instrumentation.
| "tdd:browser": "karma start", | ||
| "test:cjs": "nyc mocha 'test/**/*.test.ts' --exclude 'test/browser/**/*.ts'", | ||
| "test:esm": "nyc node --experimental-loader=./hook.mjs ../../../node_modules/mocha/bin/mocha 'test/node/*.test.mjs' test/node/*.test.mjs", | ||
| "test:esm": "nyc node --experimental-loader=./hook.mjs ../../../node_modules/mocha/bin/mocha 'test/node/*.test.mjs'", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewer note: I think this was a typo from when this was originally added. The additional test/node/*.test.mjs arg is redundant.
| Object.defineProperty(moduleExports, name, { | ||
| value: wrapped, | ||
| }); | ||
| return wrapped; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewer note: From a quick check, I didn't see any core or contrib-repo instrumentations using the return value of this._wrap. Arguably this is a "fix" for @opentelemetry/instrumentation, but I didn't mention it in the CHANGELOG.
experimental/packages/opentelemetry-instrumentation/test/node/EsmInstrumentation.test.mjs
Show resolved
Hide resolved
maryliag
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a nit, otherwise LGTM
|
@trentm sorry I'm terrible with acronyms, what IITM means? |
My bad: It is import-in-the-middle (https://github.com/nodejs/import-in-the-middle). (And often RITM for require-in-the-middle.) |
hectorhdzg
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
JamieDanielson
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, thanks for working on this! Appreciate the test updates as well. I left a few nits around the tests but the functionality itself is good. I'm now wondering about other instrumentations and what can be done there... but for now 🚀
experimental/packages/opentelemetry-instrumentation-http/test/integrations/esm.test.mjs
Outdated
Show resolved
Hide resolved
experimental/packages/opentelemetry-instrumentation-http/test/integrations/esm.test.mjs
Outdated
Show resolved
Hide resolved
experimental/packages/opentelemetry-instrumentation-http/test/integrations/esm.test.mjs
Outdated
Show resolved
Hide resolved
experimental/packages/opentelemetry-instrumentation-http/test/integrations/esm.test.mjs
Outdated
Show resolved
Hide resolved
| moduleExports => { | ||
| this._wrap(moduleExports, 'testFunction', () => { | ||
| return () => 'patched'; | ||
| const wrapRetval = this._wrap(moduleExports, 'testFunction', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| const wrapRetval = this._wrap(moduleExports, 'testFunction', () => { | |
| const wrappedReturnValue = this._wrap(moduleExports, 'testFunction', () => { |
This is a total nit, but I wonder if we could use a full name for this - primarily because this tends to be a confusing functionality and I'm a sucker for detailed variable names. Maybe something like patchedModule, similar to the patchedRequest you have in the http code? Nonblocking, especially since it's a test.
experimental/packages/opentelemetry-instrumentation-http/test/integrations/esm.test.mjs
Outdated
Show resolved
Hide resolved
|
Also I think this updates open-telemetry/opentelemetry-js-contrib#1942 now for http instrumentation? |
Co-authored-by: Jamie Danielson <[email protected]>
Co-authored-by: Jamie Danielson <[email protected]>
Co-authored-by: Jamie Danielson <[email protected]>
Co-authored-by: Jamie Danielson <[email protected]>
| const clientReq = https.request( | ||
| `https://127.0.0.1:${port}/https.request`, | ||
| { | ||
| rejectUnauthorized: false, |
Check failure
Code scanning / CodeQL
Disabling certificate validation
| https.get( | ||
| `https://127.0.0.1:${port}/https.get`, | ||
| { | ||
| rejectUnauthorized: false, |
Check failure
Code scanning / CodeQL
Disabling certificate validation
…https.get` work when used in ESM code (open-telemetry#4866) * fix(instrumentation-http): Ensure instrumentation of `http.get` and `https.get` work when used in ESM code The issue was that the `_wrap`ing of `http.get` was getting the just-wrapped `http.request` by accessing `moduleExports.request`. However, when wrapping an ES module the `moduleExports` object from IITM is a Proxy object that allows setting a property, but *not* re-getting that set property. The fix is to use the wrapped `http.request` from the `this._wrap` call. That required fixing a bug in the IITM code-path of `InstrumentationBase.prototype._wrap` to return the wrapped property. (The previous code was doing `return Object.defineProperty(...)`, which returns the moduleExports, not the defined property.) Fixes: open-telemetry#4857 * correct typo in the changelog message * does this fix the test:esm script running on windows? * remove other console.logs (presumably dev leftovers) from tests in this file * test name suggestion Co-authored-by: Jamie Danielson <[email protected]> * test name suggestion Co-authored-by: Jamie Danielson <[email protected]> * test name suggestion Co-authored-by: Jamie Danielson <[email protected]> * test name suggestion Co-authored-by: Jamie Danielson <[email protected]> * var naming suggestion: expand cres and creq, the abbrev isn't obvious --------- Co-authored-by: Jamie Danielson <[email protected]>
The issue was that the
_wraping ofhttp.getwas getting thejust-wrapped
http.requestby accessingmoduleExports.request.However, when wrapping an ES module the
moduleExportsobject from IITMis a Proxy object that allows setting a property, but not re-getting
that set property.
The fix is to use the wrapped
http.requestfrom thethis._wrapcall.That required fixing a bug in the IITM code-path of
InstrumentationBase.prototype._wrapto return the wrapped property.(The previous code was doing
return Object.defineProperty(...), whichreturns the moduleExports, not the defined property.)
Fixes: #4857