-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Feature request: proper full hapi support #2172
Comments
Thanks for the suggestion! Our roadmap for Q2 is pretty set, but I've added it to our backlog as something to consider in the future. In the meantime, we're always open to contributions from the community! |
Hi @lobsterkatie, I think a good start would be to take a quick look at https://github.com/hydra-newmedia/hapi-sentry and see if that implementation makes sense and is not missing anything obvious. It is missing tracing possibilities though. server.ext('onRequest', (request, h) => {
// Based on https://github.com/getsentry/sentry-javascript/blob/533975107d9978bcae0b78f61ac214dff4e9ad14/packages/node/src/handlers.ts#L50
const transaction = Sentry.startTransaction({
op: 'http.server',
name: `${request.method.toUpperCase()} ${request.path}`
}, {
request: Sentry.Handlers.extractRequestData(request.raw.req)
});
Sentry.configureScope((scope) => {
scope.setSpan(transaction);
});
request.app.sentry = {
transaction
};
return h.continue;
});
server.events.on('response', (request) => {
request.app.sentry.transaction.name = `${request.method.toUpperCase()} ${request.route.path}`; // Set parameterized as transaction name e.g.: `GET /users/{id}`
request.app.sentry.transaction.setHttpStatus(request.response.statusCode);
request.app.sentry.transaction.setData('url', request.path);
request.app.sentry.transaction.setData('query', request.query);
request.app.sentry.transaction.finish();
}); I think it might warrant its own issue but a big part of what is missing is the use of Async Hooks. I've been in contact with your support as well so let me know where I best keep communicating. |
This is the best place to continue the conversation. We currently still support node 6, which doesn't have async hooks, so for the moment at least, we can't do that. I would be curious to see how you're envisioning using them for this, though. And while I grant that the use of domains is deprecated, I checked and it's been deprecated ever since node 4, and we're now on node 16. Domains are still here, we know they work for our use case and are likely not changing, and we've yet to find an alternative we think is better. If you think async hooks might be that alternative in the future (after we drop node 6 support someday), I'm interested to hear about it. For the moment, though, we're going to stick with domains. |
This reply reads very dismissive (which I hope it is not). While I don't think you should still support node 6 for various reasons (support, security, ...) you probably (hopefully) have good business reasons for this, so I won't argue that point. Sadly this impacts every other customer not on node 6 (which I hope is the majority). It would be nice if the SDK would detect the node version and use the best possible solution for that version. So domains on node 6 and hooks on node 8 (might need to be 8.5 or something). You state that domains code won't change while it did in (I believe) node 10. See nodejs/node#16222. You also stated you know domains will work as long as they exist, which is true I guess but this is also the case for hooks? Hooks might actually receive some changes in the future but those would be to make things easier or more performant. The reason domains are not gone yet is because of userland usage. I don't see node dropping hooks for the same reason. It would break almost all apm agents at this point.
I might be misreading your point but if you want to see how to use hooks for traces: |
I apologize - that was certainly not my intent. Full disclosure, the question of whether or not to continue using domains has come up many times before, and often turned into a lot of back and forth, and wanting to avoid that is probably what you were hearing. But that's not on you, so again, apologies! And I have to hand it to you - you have done your research! I will bring this back to the team to see what they think. While there's enough on our docket that we're unlikely to make any independent changes here in the short term, we do have an upcoming goal of re-evaluating our performance API, so perhaps this could be rolled into that. I'll add it in as a note in our planning doc. Thanks. |
This doesn't only impact the performance api. This also impacts things like breadcrumbs on errors. I do think that not having proper tracing with async hooks out of the box makes the Sentry agent way less interesting. I think those are things that are easily fixable by just clearly stating them in the docs (which are otherwise very nice and clear in general). I'm happy to talk further about how the tracing could look or how to best handle adding hapi support (or officially endorsing https://github.com/hydra-newmedia/hapi-sentry or something) |
I've been testing to see if we can use the domain based solution until the agent catches up. I'm still seeing db spans being thrown together on 1 transaction instead of properly on each transaction. This is my current test code: server.ext('onRequest', (request, h) => {
request.app.sentry = {};
// Domain stuff based on https://github.com/hydra-newmedia/hapi-sentry/blob/283f0f8966c03d8a1f5a4b3a7a2709ba3b93858e/index.js#L41
// Sentry looks for current hub in active domain
// Therefore simply by creating and entering domain Sentry will create
// request scoped hub for breadcrumbs and other scope metadata
request.app.sentry.domain = Domain.create();
request.app.sentry.domain.enter();
// Based on https://github.com/getsentry/sentry-javascript/blob/533975107d9978bcae0b78f61ac214dff4e9ad14/packages/node/src/handlers.ts#L50
const transaction = Sentry.startTransaction({
op: 'http.server',
name: `${request.method.toUpperCase()} ${request.path}`
}, {
request: Sentry.Handlers.extractRequestData(request.raw.req) // Passed to transaction sampling function
});
Sentry.configureScope((scope) => {
scope.setSpan(transaction);
});
request.app.sentry.transaction = transaction;
return h.continue;
});
// Same result with `server.ext('onPostAuth'`, lifecycle ref https://futurestud.io/files/hapi/hapi-request-lifecycle.pdf
server.events.on('response', (request) => {
request.app.sentry.transaction.name = `${request.method.toUpperCase()} ${request.route.path}`; // Set parameterized as transaction name e.g.: `GET /users/{id}`
request.app.sentry.transaction.setHttpStatus(request.response.statusCode);
request.app.sentry.transaction.setTag('http.method', request.method.toUpperCase()); // Attempt to set the http method on the performance dashboard, but it seems like it only attaches it when an error happens. So probably not the correct way.
request.app.sentry.transaction.setTag('http.url', request.path); // For filtering, although the dashboard doesn't seem to like it atm
request.app.sentry.transaction.setData('url', request.path);
request.app.sentry.transaction.setData('query', request.query);
request.app.sentry.transaction.finish();
// Exiting domain
request.app.sentry.domain.exit();
});
// not exact but technically the same
server.ext('onPostAuth', (request, h) => {
// Set user info for Sentry
Sentry.configureScope((scope) => {
scope.setUser({ ...request.auth.credentials });
});
return h.continue;
}); Am I missing something obvious or doing something wrong? |
Hi, I made a general issue for the async hooks over here: #3660 as it seemed to sidetrack this issue, which is about hapi support. I'm still looking forward to a reply, hoping I messed something up so we can actually use Sentry for performance tracing. |
Tracking in #6973 - closing this issue until we start work on it. |
I know that express and koa are supported but it would be nice if hapi would also be supported out of the box.
I think this is mostly about proper handling of request data.
I think the express integration is exposed as middleware, you could do the same for hapi, there is called a plugin.
The text was updated successfully, but these errors were encountered: