-
Notifications
You must be signed in to change notification settings - Fork 30.1k
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
fetch: design of wrapper makes instrumenting miss the first request #43915
Comments
@targos I see you added the lazy loading in 4944ad0b9ed. Any thoughts on making this more malleable for instrumentation vendors? Ideally it'd be nice to always load at runtime so we can properly subscribe to the undici channels before any fetch requests have been made |
I'm sorry, I don't understand the problem enough to suggest a solution. Why can't you subscribe to the diagnostics channels before undici is loaded? |
@targos I'm not 100% certain but maybe because undici is getting required through the internal loader and the WeakReference is lost? If I create the subscriptions before undici is loaded I see the channels in the diagnostics channel but the ref is undefined when undici calls // channel.js:
'use strict'
const diagnosticChannel = require('diagnostics_channel')
diagnosticChannel.channel('diag-test').subscribe((name) => {
console.log(`Hello ${name}`)
}) // main.js
'use strict'
require('./channel')
const diagnosticsChannel = require('diagnostics_channel')
function doStuff() {
console.log('doing stuff')
}
debugger
const channel = diagnosticsChannel.channel('diag-test')
if (channel.hasSubscribers) {
channel.publish('Bob')
} |
With all this being said, this appears to be a registration order of instrumentation within our agent. I've yet to find root cause but I'm going to close this for now. |
I'd still like to bring this to the attention of @nodejs/diagnostics |
Use diagnostics_channel.subscribe(name, handler). The channel.subscribe(handler) API is deprecated. If you really must use the channel object subscriber, you should make sure the channel object reference is held somewhere as it will otherwise get garbage collected immediately after use due to being a weak reference within diagnostics_channel. |
Thanks for your feedback @Qard I will update our instrumentation and save references to ensure GC doesn't clean up. |
@Qard which version of Node.js is |
Also FWIW I did this and it still didn't work
I basically set something up like this
But when undici is internally required and when it creates the channels, the weak references are gone for my subscription handlers. As I mentioned here, something in our bootstrap process is affecting this. I was hoping doing what you suggested by saving references to channels would help but it appears it did not |
The new API isn't available in a release yet. It was added in #42714 |
Ah, yeah, it was merged awhile ago now, but I guess no new releases with it yet. As for the channel getting collected, the way the original API was supposed to be used was by declaring the channels immediately after the requires at the top of the file and storing them somewhere that can be reached by wherever the publish or subscribe calls will happen. This turned out to be a bit problematic because subscribers sometimes also would happen at top-level, which resulted in people chaining the subscribes which would let the whole thing fall out-of-scope immediately. This is why the new API was introduced which explicitly marks the link as strong. |
I'm revisiting this and I think it's the same reason detailed out in #42170 |
What is the problem this feature will solve?
fetch shipped in 18.x which is a wrapper around undici. I work on the New Relic Node.js agent and we noticed an issue where we weren't properly propagating state through a fetch command. When I tried registering our undici instrumentation, I noticed the first request is missed.
This is due to the lazy loading of the internal undici. Also since this is an internal module load I couldn't rely on our CJS instrumentation to key off of a require of a file path.
What is the feature you are proposing to solve the problem?
Change how undici is getting loaded as an internal to make it possible to properly register channels before the first fetch is ever called. Also as aside, I may be wrong but making fetch async is creating an unnecessary promise right?
What alternatives have you considered?
The above code snippet feels like the only option which will miss the first request as the subscriptions are not present. I guess an alternative would be users to preemptively subscribe to channels but I get how that could be problematic and lead to hijacking of name spaces.
The text was updated successfully, but these errors were encountered: