-
Notifications
You must be signed in to change notification settings - Fork 2k
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
Usage reporting: report referenced fields in addition to executed fields #5956
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
In Apollo Studio, the "Fields" page lets you see how often your fields are *executed* by operations --- ie, how often their resolvers run. It additionally lets you see which clients and operations ran those operations. However, knowing if an operation *executed* a field doesn't tell the whole story about the relationship between operations and fields. You might also be curious to learn if a field was textually referenced in the operation itself. It's possible for a field to be referenced without executing. In fact, there are many reasons this can happen: - The field is nested under another field which evaluates to null - The field is nested under another field which evaluates to an empty list - The field is nested under a non-matching fragment - The field is nested under `@include` or `@skip` If you're using the Fields page to determine "what are all the operations that use this field", you probably want to know about these usages too! It's also possible for a field to be executed without being referenced. That's because when we track "executed fields", we are always tracking the concrete object type that is being executed, not an interface type it may have been resolved through. So with schema: ```graphql interface Animal { legs: Int } type Dog implements Animal { legs: Int } type Query { myFavoriteAnimal: Animal # In practice, always returns a Dog } ``` the operation `{ myFavoriteAnimal { legs } }` "references" `Animal.legs`, not `Dog.legs`, but it is the field `Dog.legs` that is executed. (Additionally, when using federation, fields can be executed without being referenced in the operation if the query plan requires them to be executed to fulfill an `@requires` or `@key` directive.) This PR extends Apollo Server's usage reporting plugin to provide a list of "referenced fields" along with every operation. Note that these fields depend only on the operation, not on the variables passed or anything at execution time, so we don't need one set per trace, just one set per operation. In addition to the fact that this statistic is an interesting one, this will also mean that the Fields page can be useful without needing full execution tracing. There is a real performance impact of full execution tracing, especially in the federation context where the ftv1 protocol involves sending subgraph traces to the gateway/router in-band in the response. And not every GraphQL server supports full execution tracing in the first place. With support for referenced fields on the Fields page, you will be able to run a gateway/router in front of an arbitrary subgraph without federated tracing (whether you want to do this for performance or lack of implementation reasons) and still get some useful data on the Fields page. (You can then perhaps run full tracing on a sampled subset of queries to get reasonable approximate execution data too.) Note that the new Studio functionality may not be in general availability when this PR merges into the Apollo Server release branch or when the first alphas are created; it will be fully enabled (including docs) by the time this PR is released in a non-prerelease. As part of the implementation, we extend the existing "signature cache" to cache the referenced field list as well. Note that the signature is a pure function of the operation, whereas the referenced field list also depends on the schema, so we add a little mechanism to throw out the cache if the schema changes. Fixes #5708.
trevor-scheer
approved these changes
Dec 17, 2021
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few minor comments, LGTM. Don't forget a changelog entry.
packages/apollo-server-core/src/plugin/usageReporting/__tests__/referencedFields.test.ts
Outdated
Show resolved
Hide resolved
packages/apollo-server-core/src/plugin/usageReporting/plugin.ts
Outdated
Show resolved
Hide resolved
packages/apollo-server-core/src/plugin/usageReporting/referencedFields.ts
Show resolved
Hide resolved
CHANGELOG update: a66ad28 |
trevor-scheer
approved these changes
Dec 17, 2021
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome, thanks for all the good test additions 👍
Merged
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
In Apollo Studio, the "Fields" page lets you see how often your fields
are executed by operations --- ie, how often their resolvers run. It
additionally lets you see which clients and operations ran those
operations.
However, knowing if an operation executed a field doesn't tell the
whole story about the relationship between operations and fields. You
might also be curious to learn if a field was textually referenced in
the operation itself.
It's possible for a field to be referenced without executing. In fact,
there are many reasons this can happen:
list
@include
or@skip
If you're using the Fields page to determine "what are all the
operations that use this field", you probably want to know about these
usages too!
It's also possible for a field to be executed without being referenced.
That's because when we track "executed fields", we are always tracking
the concrete object type that is being executed, not an interface type
it may have been resolved through. So with schema:
the operation
{ myFavoriteAnimal { legs } }
"references"Animal.legs
, notDog.legs
, but it is the fieldDog.legs
that isexecuted.
(Additionally, when using federation, fields can be executed without
being referenced in the operation if the query plan requires them to be
executed to fulfill an
@requires
or@key
directive.)This PR extends Apollo Server's usage reporting plugin to provide a list
of "referenced fields" along with every operation. Note that these
fields depend only on the operation, not on the variables passed or
anything at execution time, so we don't need one set per trace, just one
set per operation.
In addition to the fact that this statistic is an interesting one, this
will also mean that the Fields page can be useful without needing full
execution tracing. There is a real performance impact of full execution
tracing, especially in the federation context where the ftv1 protocol
involves sending subgraph traces to the gateway/router in-band in the
response. And not every GraphQL server supports full execution tracing
in the first place. With support for referenced fields on the Fields
page, you will be able to run a gateway/router in front of an arbitrary
subgraph without federated tracing (whether you want to do this for
performance or lack of implementation reasons) and still get some useful
data on the Fields page. (You can then perhaps run full tracing on a
sampled subset of queries to get reasonable approximate execution data
too.)
Note that the new Studio functionality may not be in general
availability when this PR merges into the Apollo Server release branch
or when the first alphas are created; it will be fully enabled
(including docs) by the time this PR is released in a non-prerelease.
As part of the implementation, we extend the existing "signature cache"
to cache the referenced field list as well. Note that the signature is a
pure function of the operation, whereas the referenced field list also
depends on the schema, so we add a little mechanism to throw out the
cache if the schema changes.
Fixes #5708.