-
Notifications
You must be signed in to change notification settings - Fork 539
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
Express doesn't get instrumented with ESM #1849
Comments
Seems you use ECMA script modules. Support is experimental and requires some extra love on how you call node. see here |
If I run it with that prefix, I get a logline after the debug output saying:
but no events sent to honeycomb at all. Removing that again, http events show up. |
I'm taking a look into this. The |
I guess this is similar to some of our other ESM problems. I can do a very small reproducer using just the ExpressInstrumentation (not fully set up to instrument, just to show the problem) that I believe is a good indicator of the problem, and I think it's related to how modules are loaded in ESM vs CJS. import { diag, DiagConsoleLogger, DiagLogLevel } from '@opentelemetry/api';
diag.setLogger(new DiagConsoleLogger(), DiagLogLevel.DEBUG);
import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
new ExpressInstrumentation();
import express from 'express';
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => console.log('Example app listening on port 3000!')); This ESM app ✗ node --experimental-loader=@opentelemetry/instrumentation/hook.mjs test.mjs
(node:16336) ExperimentalWarning: Custom ESM Loaders is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
@opentelemetry/api: Registered a global for diag v1.6.0.
@opentelemetry/instrumentation-express Module express has been loaded before @opentelemetry/instrumentation-express so it might not work, please initialize it before requiring express
Example app listening on port 3000! An identical app called ✗ node test.cjs
@opentelemetry/api: Registered a global for diag v1.6.0.
Applying patch for [email protected]
Example app listening on port 3000! In both, the order of everything in the code is identical. This will need more time to sort out. |
I am encountering the same issue. I created a reduced test case before discovering this issue. Sharing in case it's helpful: https://github.com/OliverJAsh/esm-otel. As the reduced test case demonstrates, this issue also affects the Pino instrumentation. |
@kevinmarks sorry for the delay on this, I had gotten stuck on it and picked up some other things in the meantime. I've come back around to it and believe I have a solution as I was able to use your example repro. The key issue is that express is getting loaded before the instrumentation can monkey-patch it. So we can use top-level awaits available in ESM to solve this. The main changes I made to make your app work were to make the tracing an async function with an awaited default export, and then await the import of express in the app. I also ran the start command with the loader hook. // tracing.mjs
...
export const startTracing = async () => {
const node_sdk = new NodeSDK({
...
});
node_sdk.start()
}
export default await startTracing; // index.mjs
import startTracing from './tracing.mjs';
startTracing();
const expressModule = await import('express');
const express = expressModule.default;
... Now with debug enabled, my log includes the patch logs I expect, and hitting the endpoint results in spans for http and express. ➜ OT-testbed git:(main) ✗ npm run start:mjs
> [email protected] start:mjs
> node --experimental-loader=@opentelemetry/instrumentation/hook.mjs ./index.mjs
...
@opentelemetry/instrumentation-http Applying patch for [email protected]
Applying patch for net module
Applying patch for [email protected]
OT-testbed Listening on 3000
... Would you be able to give this a try with your app and confirm it works properly? |
Actually you might even be able to keep your app and tracing module as is, and instead change the start script to ensure the tracing file is loaded first. |
Doing some testing as @JamieDanielson said and this also seems to do the trick, just in case for those who want to use
Tested in node 20.12.1 with Express 4.18.2 |
|
@vchirikov If you are able to help provide more details, it would be best to open a separate issue to for getting things working with Astro. Ideally that would include a small and complete reproduction so maintainers don't have to learn how to build an astro-based app. My total guess is that astro is a web framework that is doing bundling. If so, then bundling currently breaks any auto-instrumentation because included packages are no longer loaded using |
OfftopicAstro is based on vite, vite uses ESM. The first error was `SyntaxError: The requested module './bundle-full.mjs' does not provide an export named 'codeToHast'` from `shiki` and some of astro internals (`dist/cookies` as far as I can remember). It's an issue with `import-in-the-middle`. I found a workaround - hook ONLY the desired modules (`node:*` in my case), I have to create a git patch to do it (with `patch-package`), but at least it works. Anyway, I think the usage of opentelemetry-js packages should be much easier & better documented. |
This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 14 days. |
still Offtopic
I hope that OTel will get to doing that by default now that import-in-the-middle supports it via nodejs/import-in-the-middle#146 |
@JamieDanielson, thanks for good explanation! |
@atsu85 this should work with the suggestions listed above. I've finally added a doc with these details as well, which I'm working on getting into the main docs site. |
I will close this specific issue with the above note but if any new issues arise please feel free to open a new issue! |
What version of OpenTelemetry are you using?
What version of Node are you using?
v16.20.1
What did you do?
Instrumented a minimal node app with honeycombio
What did you expect to see?
Traces that included the express auto instrumentation
What did you see instead?
Traces that only included http and net instrumentation
Additional context
Example project here - needs a honeycomb api key in telemetry.mjs to run
https://github.com/kevinmarks/OT-testbed
The text was updated successfully, but these errors were encountered: