-
Notifications
You must be signed in to change notification settings - Fork 62
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
Node.js server integration - isolated context per request #708
Comments
Hey @shalvah, thank you for submitting this! I already have some thoughts on how to implement this; I will put them in writing here (in a day or two) and we can discuss. |
Thoughts: Manual wrappingWrap the request handler in als.run(). But this will require the users to wrap each of their request handlers, and I don't know if we want to add that friction. MiddlewareWe could use an Express middleware, that does something like This might be good for Express users, but we need to be intentional about error handling, since als.run() returns a promise, and Express v4 does not natively handle promise handlers correctly. If we go with this, we'd then have to provide similar middleware for other frameworks, or fall back to the wrapping method for unsupported frameworks. Local instantiationThere might also be a non-ALS option: tell users to instantiate the Honeybadger client on each request. A middleware like: app.use((req, res, next, err) => {
req.hb = Honeybadger.(...);
}); But:
Monkey-patchingThis might provide the best UX, but involved the worst code. We could hook into Express and overwrite its request handling so that it internally runs each request in a local HB context. I believe some APM libraries do something similar. Pros: The user would likely not need to make any code changes. Final thoughtsI haven't really thought this through wholly, but I suspect we might be able to use async_hooks and drop deeper than ALS for an alternative approach.) |
@subzero10 are you already on this, or can I pick it up? I've got an app I'd like to track with Honeybadger, but the "leaking context" is a pain to work around. |
No I'm not, you can go ahead! |
@joshuap what do you think of these approaches? |
@shalvah How about we do the middleware solution for frameworks that we already provide middleware ( |
Right. And for non-supported frameworks, maybe we provide a |
Hmm, I'm not sure, I haven't seen such feature in other tools. I think I need to think/research about this more. |
Elastic APM uses a mix: they patch the Sentry...seems to also have the same issue we do. Example report, tracking issue. Welp. |
I think I'll go with the custom middleware/hb.run(...) approach. I like that monkey-patching needs no end user code changes, but it can go hairy quickly.
I generally try to do less monkey-patching these days, for reasons like these. The middleware/wrapper approach would gracefully support Express and other frameworks with a simple code addition. |
I like the middleware/run approach. We can always go deeper in the future, but I agree with what you said about monkeypatching. |
Like #688, but for traditional single-threaded, server-side Node.js apps. The goal is to ensure that context does not "spill over" across concurrent requests being handled by the same process.
Problem
First, a simple proof of concept (tested with the included express example):
Then make two concurrent requests (I use autocannon):
Terminal logs:
You can see the problem—the context is shared globally.
Fix
AsyncLocalStorage
Thankfully, @subzero10 has already implemented the stores in his recent PR to start this off.
To Do:
cc @subzero10 @joshuap
The text was updated successfully, but these errors were encountered: