Skip to content

Conversation

@onurtemizkan
Copy link
Collaborator

@onurtemizkan onurtemizkan commented Sep 2, 2021

Summary:

This PR introduces basic tracing functionality for server-side GraphQL query resolutions.
My original intent was to implement a single generic integration for GraphQL but trying to patch resolvers inside graphql-js ended up being very painful (if not impossible) as most of the resolver-level execution logic is strictly unexposed and there seem to be no instances that store resolvers we can monkey-patch.

So I ended up implementing two integrations for both GraphQL and Apollo.

  • GraphQL integration has very basic functionality and simply works as the parent node for all resolvers in the execution tree when used with Apollo. Without Apollo, it's just a simple span for the whole GQL execution process. But may still be useful.

  • Apollo integration works on the resolver level, supports nested resolutions, and treats DB operations as children.

I think there is a lot of room for improvement for both integrations. But wanted to get opinions and reviews before investing more time in them.

Resolves: #3774

@github-actions
Copy link
Contributor

github-actions bot commented Sep 2, 2021

size-limit report

Path Size
@sentry/browser - CDN Bundle (gzipped) 22.49 KB (+0.02% 🔺)
@sentry/browser - Webpack 23.37 KB (0%)
@sentry/react - Webpack 23.4 KB (0%)
@sentry/browser + @sentry/tracing - CDN Bundle (gzipped) 29.96 KB (+0.13% 🔺)
@onurtemizkan onurtemizkan marked this pull request as ready for review September 3, 2021 13:02
@kamilogorek kamilogorek marked this pull request as draft September 14, 2021 14:48
@kamilogorek kamilogorek marked this pull request as ready for review September 14, 2021 14:49
@kamilogorek kamilogorek changed the title [WIP] feat(tracing): GraphQL and Apollo Integrations Sep 14, 2021
@thinkocapo
Copy link

Hi @onurtemizkan I worked with these developers on these blog articles, this one used a Resolver in his approach too
https://blog.sentry.io/2021/08/31/guest-post-performance-monitoring-in-graphql

and this used didEncounterErrors for error monitoring
https://blog.sentry.io/2020/07/22/handling-graphql-errors-using-sentry

@onurtemizkan
Copy link
Collaborator Author

Hi @thinkocapo, yeah I guess that's the sensible way to trace GraphQL transactions. Just if we could track GraphQL resolvers without relying on Apollo (as resolver is a core GraphQL concept), our plugin would be available for a wider range of projects. But still, this works, and most projects are using Apollo anyways, so we should be fine for now.

@github-actions
Copy link
Contributor

This pull request has gone three weeks without activity. In another week, I will close it.

But! If you comment or otherwise update it, I will reset the clock, and if you label it Status: Backlog or Status: In Progress, I will leave it alone ... forever!


"A weed is but an unloved flower." ― Ella Wheeler Wilcox 🥀

@andreialecu
Copy link
Contributor

Hi @onurtemizkan I worked with these developers on these blog articles, this one used a Resolver in his approach too blog.sentry.io/2021/08/31/guest-post-performance-monitoring-in-graphql

and this used didEncounterErrors for error monitoring blog.sentry.io/2020/07/22/handling-graphql-errors-using-sentry

The approach in the first blog post doesn't work properly when batching is involved, or when a request contains multiple queries.

Here's a more detailed report of what I mean: https://forum.sentry.io/t/transactions-with-graphql/13702

To clarify, it completely breaks down with https://www.apollographql.com/docs/react/api/link/apollo-link-batch-http/

I'm hoping the approach in this PR works better in this regard.

Is there anything missing here?

@rhcarvalho
Copy link
Contributor

Hi @onurtemizkan! Could you please help me summarize the current status for this PR?

Are we settled on the current approach?
Any drawbacks to be documented?
Any work pending?
Ready for a pass of code reviews?
What are the most important decisions and assumptions that were made that reviewers should be aware of?

Thanks!

@onurtemizkan
Copy link
Collaborator Author

Hi @rhcarvalho. At this stage, it would be wonderful to get some reviews about the approach taken.

The summary of this approach:

  • The original request about tracing functionality [Apollo tracing integration package? #3774] was about tracing resolvers that may or may not contain database operations.

  • To generalize it, since resolver is a GraphQL concept, and Apollo itself uses graphql-js internally to execute provided resolvers, I tried to monkey-patch/wrap those resolvers or their wrappers to create a single GraphQL integration. But, it was not possible because the implementation of graphql-js isn't exposed, and I couldn't find an alternative way around it.

  • But it exposes the whole execution process which is the parent of all parallel/serial resolvers. It is actually a quite rough information. Still, it feels worthwhile to track. (Please correct me if I'm wrong).

  • After all, to track resolvers, Apollo's constructSchema appeared to be the most relevant and approachable method to access them and their hierarchy (the resolvers object still contain the parent/child relationship in a tree structure, when passed as an argument to constructSchema).

  • These two integrations work together when used with an Apollo server project, where the GraphQL span is the container and resolvers are children (grand-times-x children). Resolvers also can be parents of db operations from any of our database tracing instrumentations.

I'll be happy to put more work on this PR to refine/test more, after getting reviews, but this implementation has the basic functionality and is working in the current state.

@kamilogorek kamilogorek removed their request for review March 2, 2022 20:34
@onurtemizkan onurtemizkan force-pushed the onur/graphql-tracing-integration branch from 69c89f9 to 94074fc Compare April 14, 2022 07:38
@onurtemizkan onurtemizkan changed the base branch from master to 7.x April 14, 2022 07:38
@github-actions
Copy link
Contributor

github-actions bot commented Apr 14, 2022

size-limit report 📦

Path Size
@sentry/browser - ES5 CDN Bundle (gzipped + minified) 19.43 KB (added)
@sentry/browser - ES5 CDN Bundle (minified) 60.2 KB (added)
@sentry/browser - ES6 CDN Bundle (gzipped + minified) 18.24 KB (added)
@sentry/browser - ES6 CDN Bundle (minified) 53.82 KB (added)
@sentry/browser - Webpack (gzipped + minified) 19.99 KB (added)
@sentry/browser - Webpack (minified) 65.19 KB (added)
@sentry/react - Webpack (gzipped + minified) 20.02 KB (added)
@sentry/nextjs Client - Webpack (gzipped + minified) 43.95 KB (added)
@sentry/browser + @sentry/tracing - ES5 CDN Bundle (gzipped + minified) 25.56 KB (added)
@sentry/browser + @sentry/tracing - ES6 CDN Bundle (gzipped + minified) 24.11 KB (added)
@onurtemizkan onurtemizkan force-pushed the onur/graphql-tracing-integration branch 2 times, most recently from 311dc78 to c634e2c Compare April 14, 2022 16:01
Comment on lines 241 to 257
apollo() {
const integration = dynamicRequire(module, './integrations/apollo') as {
Apollo: IntegrationClass<Integration>;
};
return new integration.Apollo();
},
graphql() {
const integration = dynamicRequire(module, './integrations/graphql') as {
GraphQL: IntegrationClass<Integration>;
};
return new integration.GraphQL();
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh I'd rather make these opt-in rather than auto-enabled.

Any possible way we can integration test this? We can do it in the PR moving forward as well.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AbhiPrasad, updated and added the tests. 👍 Docs are coming up.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make sure these are not auto-enabled?

@AbhiPrasad
Copy link
Member

We'll also need docs for this!

@onurtemizkan onurtemizkan force-pushed the onur/graphql-tracing-integration branch 4 times, most recently from beed667 to 4dcc09e Compare April 21, 2022 18:19
@@ -0,0 +1,33 @@
import { assertSentryTransaction, getEnvelopeRequest, runServer, conditionalTest } from '../../../utils';

conditionalTest({ min: 12 })(() => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not supported by node 10?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, can we leave a comment above the test linking to the package.json?

@onurtemizkan onurtemizkan force-pushed the onur/graphql-tracing-integration branch from 44e8e46 to f520528 Compare June 9, 2022 16:04
@onurtemizkan onurtemizkan changed the base branch from 7.x to master June 9, 2022 16:05
@onurtemizkan onurtemizkan force-pushed the onur/graphql-tracing-integration branch from f520528 to 117a868 Compare June 9, 2022 16:23
@lforst
Copy link
Contributor

lforst commented Jun 10, 2022

Thanks for this @onurtemizkan! Let's not forget to merge getsentry/sentry-docs#5089 when this is released.

@lforst lforst merged commit cafd6cb into master Jun 10, 2022
@lforst lforst deleted the onur/graphql-tracing-integration branch June 10, 2022 09:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

8 participants