-
Notifications
You must be signed in to change notification settings - Fork 807
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
nodejs 18: Support native fetch #3413
Comments
Hmm the instrumentation shouldn't depend on the SDK package anyway so that needs to be updated. I'm not sure how easy it would be to make the browser fetch instrumentation work in both places, but that would be my preferred solution. |
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. |
This is still relevant. |
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. |
Hi @Fryuni |
I started working on a patch that would work for us, but it breaks other scenarios. I still need to work on a proper solution, but time has been eluding me. If you want to tackle this, here is what I got: The It uses only 5 functions from I used Those 5 functions do all the heavy work for the browser, like creating an empty anchor and moving a value through it to normalize things, but it doesn't seem to me like there would be a lot of work to do when in Node, so it should be quite straightforward to implement those. It could be provided as a I've been analyzing this slowly since my previous comment when I have some spare time, mostly while commuting, so I don't even have a branch for you to work from, sorry about that. 😄 |
Thanks for the update! I'll see if I can follow up on your research |
Following this too! Would be great for this instrumentation to also work for other serverside WinterCG environments (Vercel, CloudFlare Workers) |
For reference for Deno I just had to make // Monkeypatching to get past FetchInstrumentation's dependence on sdk-trace-web, which depends on some browser-only constructs
globalThis.location = {}; //For this line in parseUrl - https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-sdk-trace-web/src/utils.ts#L310 And Grunet/otel-js-deno-experimentation@8cbcc12 for the change to the modified example I've been working with |
Also wanted to cross-document here that the fetch autoinstrumentation package is currently using Date.now() instead of performance.now(), which may explain small offsets in traces (I was seeing them for Deno) More references for this at #3719 (comment) |
If you see offsets between distributed traces, it is probably due to clock skew between the services. And if |
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. |
Is anyone currently working on this? I might have a few days available to work on this during the summer, if noone else is actively on it. |
I haven't progressed on this since my comment on March, kinda left my hacky workaround there since It Just Works™️. If you wanna replicate it, replace all the functions on |
Thanks for the context! I'll try to find a bit of time to work on this 😄 |
While I work on fixing this, I want to share what I ran into: In order to make sure that trace context (via the propogation headers) was shared across services, so that an HTTP request from client -> service A -> service B showed up as 1 trace, I had to do the following with the fetch instrumentation // @ts-ignore
globalThis.location = {};
// @ts-ignore
globalThis.navigator = {};
registerInstrumentations({
tracerProvider: provider,
instrumentations: [
// other instrumentations...,
new FetchInstrumentation({
propagateTraceHeaderCorsUrls: /.*/,
}),
],
}); full snippet of my setup import { hostname } from 'os';
import { context } from '@opentelemetry/api';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
import { registerInstrumentations } from '@opentelemetry/instrumentation';
import { FetchInstrumentation } from '@opentelemetry/instrumentation-fetch';
import { Resource } from '@opentelemetry/resources';
import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base';
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
context.setGlobalContextManager(new AsyncHooksContextManager().enable());
const provider = new NodeTracerProvider({
resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: hostname() }),
});
const otlpTraceExporter = new OTLPTraceExporter({ url: process.env.OPEN_TELEMETRY_DESTINATION_URL });
provider.addSpanProcessor(new BatchSpanProcessor(otlpTraceExporter));
// @ts-ignore
globalThis.location = {};
// @ts-ignore
globalThis.navigator = {};
registerInstrumentations({
tracerProvider: provider,
instrumentations: [
// other instrumentations...,
new FetchInstrumentation({
propagateTraceHeaderCorsUrls: /.*/,
}),
],
});
provider.register(); |
another issue i want to add to this thread an issue i've encountered in the code, the _patchConstructor it seems a conscious choice was made to explicitly ignore the second argument passed to the function if the first is an instanceof You can see this handled here in the undici (node native impl) https://github.com/nodejs/undici/blob/main/lib/fetch/index.js#L125-L137 it might be necessary for this to be pulled into a bug of it's own since this would also affect the web/browser version i would imagine. |
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. |
seems #4063 is only for the web (or am I misunderstanding)? |
It makes the web SDK work when missing the web-only globals. So although it changes only the web SDK it should now work with Node (and others non-browser runtimes) |
Just tried it, it doesn't seem to be instrumenting thing I'd expect to see the way opentelemetry-instrumentation-fetch-node does |
There is a new instrumentation released a couple of weeks ago. This instrumentation works for @ehtb I think this covers point 2 right? Could you give it a try? |
@david-luna @ehtb Given the existence of the |
Closing the issue. @ehtb ping me or open a new issue if needed :) |
Node.js 18+ support the native fetch API. The current fetch instrumentation (
instrumentation-fetch
) only works in a web / browser environment. This is because it is importingsdk-trace-web
and depending onlocation
being globally defined.Before native support this was not a problem, because solutions like
node-fetch
were usinghttp
under the hood, and were therefore wrapped correctly. Now with native fetch support this is not happening anymore.I can think of these two solutions:
instrumentation-fetch
to be platform agnostic. This has the benefit of using one module consistently in multiple environmentsinstrumentation-fetch-node
which is tailored to the node.js / server environment. This would allow for easier support of some node-only utilities. Support would be for node >= 18.Could you please let me know whether support for this is in the pipeline, and perhaps from which nodejs version onward?
The text was updated successfully, but these errors were encountered: