-
Notifications
You must be signed in to change notification settings - Fork 78
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
Identify async_hooks use cases beyond AsyncLocalStorage #437
Comments
https://github.com/naugtur/blocked-at - I used async_hooks to detect the event loop blocking function. They can also be used to observe asynchronous flow execution, count number of async resources of certain type being created. None of these use cases really need access to the resource reference itself. The most valuable information is timing and stack trace form init callback in these cases. |
Added to the list. 👍 Needs we have so far:Selectively capture stack trace at init and make available in descending async contextsI believe this could be achieved through We could even have something like Record event timingsWe can already capture general timings with Another option is that this too could probably be layered on top of Do we need individual timings here, or could we reuse the Histogram interface from perf_hooks event loop monitoring but split per resource type and event type combination? |
A few of our clients uses cla-hooked to keep the request/response/user settings/logger and a lot of other critical data. The lose of context would be extremely problematic. |
Could we not just update cls-hooked to use AsyncLocalStorage internally? And probably even encourage users of it to just switch to using AsyncLocalStorage directly? They're functionally the same. Also, to be clear: I'm definitely not proposing deprecating async_hooks right away. I'm just working on clarifying the path towards being able to do that someday as it's not great that we have this unsafe API exposing internals. I want to gradually migrate all our use cases for async_hooks to safer APIs so we can someday deprecate it. |
In Bubbleprof we use async_hooks to keep track of all the states of an async activity. |
"All the states" being the async_hooks event transitions, or do you do some deeper inspection of the resource objects? If you interact with the handles directly, why? Is it possible to encapsulate any handle access needs into a new API that doesn't expose the internal handle directly? |
One feature I miss in The usecase where this is helpful are lazy initalizations of e.g. a logger, database connection,... within the first HTTP request as they stay assoziated with this request forever. I have also an idea in mind to sum up CPU and wall clock time for an async tree. This doesn't require the resource but before/after hooks. |
That propagation decision is potentially something that could be achieved with the more limited init hook that'd also be needed by the stack trace capturing and event timing needs mentioned above, if we design it right. I see something emerging there. |
@Flarna the decision about context passing (or not) is made based in resource type, not reference to the resource itself, right? |
For timers the timout would be helpful. some people use |
We just inspect the type of the handle. |
@mcollina @Qard I don't work for NearForm/clinic anymore. But one obscure usage is to detect I can understand replacing the resource object. As it is now, it is unsafe. However, I think there is value in attaching metadata to a resource. I don't get deprecating all of async_hooks, and providing higher-level APIs. I think it has always been the philosophy of node.js to provide low-level APIs to enable users to write their own modules. Deprecating async_hooks would conflict with that philosophy. |
The use case of detecting a net server is one of the use cases I see for diagnostics_channel, so I think we have a solution incoming for that. As for the low-level APIs comment: I don't think this is a low-level versus high-level thing, this is a safe versus unsafe thing. Yes, there are many other low-level APIs, but they're generally all much safer and are not exposing undocumented internals. My goal here is to find the path forward to removing unsafety, whether that be through deprecating parts of the async_hooks API or deprecating the API as a whole. This is a sketchpad/brainstorming session to figure out what the possibilities are to achieve the results we want in a better way. My personal perspective on async_hooks is that it conflates several unrelated things because one specific use case had multiple problems to solve--the context propagation need required barrier tracking and there are multiple forms of async barrier that needs to be propagated through. For mostly any other use case, the distinction between promises, timers, and libuv handles/requests is important and should probably not be presented in an aggregate form which then has to be filtered back to the form we actually want because that's just an unnecessary expense and complicates the internals. The problem with async_hooks in it's current form is actually not that it's too low-level, it's that it's an arbitrary mix of too much abstraction where none is wanted and not enough where some is needed. My ultimate goal is to raise AsyncLocalStorage to a deeper level of integration, bypassing much of the unnecessary bits of async_hooks imposed by using the user-facing API. In addition, I want to create some more purpose-focused APIs to solve the other needs of async_hooks, which can be built with a more appropriate scope. By constructing more intentionally designed APIs that only operate on what needs to be operated on, many of these scenarios can achieve much better performance, rather than just having one global firehose of every async thing ever. There's a reason async_hooks performance is still bad in many scenarios: it does too much. 😬 |
@Qard should we move this to a diag-deep-dive instead of regular agenda item? |
That could work. I tried to just go for async, but it seems to have not got a lot of engagement. A deep dive might help with that. |
Well, to be clear, we use the trace events file that contains the lifecycle information. Bubbleprof does not use async_hooks directly. So long as we could extract the same information in some kind of log (doesn't even need to be the current trace events file) then bubbleprof should still be able to do its thing. |
@jasnell FYI, bubbleprof collects stack-traces directly with async_hooks. https://github.com/clinicjs/node-clinic-bubbleprof/blob/main/injects/logger.js#L43 |
Oh that's right forgot about that piece lol ... Been a while since I opened that particular bit of the code 😂 Still, it doesn't need async hooks as a stable api to do so. We could look at extracting the data other ways. |
Looking at that particular example, seems like the skip logic is basically already covered by |
Just another data point: I've been working on a test runner, and have been using async hooks to associate resources with individual tests so that I can detect async operations that live beyond the lifetime of the test itself. |
This issue is stale because it has been open many days with no activity. It will be closed soon unless the stale label is removed or a comment is made. |
This issue is stale because it has been open many days with no activity. It will be closed soon unless the stale label is removed or a comment is made. |
It seems to be the general consensus of this working group that async_hooks should not be directly made stable due to it exposing internals. The AsyncLocalStorage API provides a higher-level solution to many of the use cases of async_hooks, however some use cases still remain. I would like to identify what those use cases are so we can introduce safer APIs solving those problems and eventually move toward deprecating direct use of async_hooks or perhaps just the unsafe aspects of it.
Known use cases:
What other use cases are there? I know clinic uses it for some things, perhaps @mcollina has some insight on that?
The text was updated successfully, but these errors were encountered: