-
Notifications
You must be signed in to change notification settings - Fork 3
Fully Qualified Operation Name (FQON) #7
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
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
0463d68
Add Fully Qualified Operation Names (FQON) GAP
magicmark ed185f6
Update GAP metadata with new ID and discussion link
magicmark dac90f5
Update README.md
magicmark fa447d6
Add summary to metadata for GAP-0
magicmark a1e6ed7
Rename GAP-0 to GAP-7
magicmark File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| # Fully Qualified Operation Name (FQON) | ||
|
|
||
| **Introduction** | ||
|
|
||
| :: This document specifies _Fully Qualified Operation Name_ (FQON), a | ||
| human‑readable, unambiguous identifier for GraphQL operations. | ||
|
|
||
| The primary motivation is to define a "lookup key" that may be used in static | ||
| configuration files (e.g. for alerting rules per operation) which correctly | ||
| targets operations, but without having to update the configuration each time a | ||
| _document id_ changes. | ||
|
|
||
| This specification assumes usage of | ||
| [trusted documents](https://graphql.org/learn/security/#trusted-documents) and | ||
| [Git version control](https://git-scm.com/). | ||
|
|
||
| **Example** | ||
|
|
||
| Given the following operation defined in a Git repository named `yelp/frontend`, | ||
| and in a package named `styleguide`: | ||
|
|
||
| ```graphql example | ||
| query GetHeaderData { | ||
| ... | ||
| } | ||
| ``` | ||
|
|
||
| The _FQON_ for this operation may be defined as: | ||
|
|
||
| ```example | ||
| GetHeaderData:styleguide:yelp/frontend:1 | ||
| ``` | ||
|
|
||
| When defining alerting rules for this operation, we can target all versions of | ||
| this operation by omitting the _version_ suffix: | ||
|
|
||
| ```example | ||
| GetHeaderData:styleguide:yelp/frontend | ||
| ``` | ||
|
|
||
| **Motivation** | ||
|
|
||
| We may identify operations using either: | ||
|
|
||
| - The _operation name_ (e.g. {"GetHeaderData"}) | ||
| - The _document id_ produced by hashing the operation body (e.g. {"605fad0ee0a88..."}) | ||
|
|
||
| Because GraphQL operation names are not be guaranteed to be globally unique, | ||
| they cannot reliably identify an operation across multiple platforms or | ||
| deployment versions. On the other hand, a _document id_ is guaranteed to be | ||
| unique but is inconvenient for humans to read and maintain. | ||
|
|
||
| Note: See <README.md> for additional context. | ||
|
|
||
| **Use Cases** | ||
|
|
||
| - A _FQON_ may be printed instead of the operation name in application logs. | ||
| This encourages correct behavior when humans use this identifier to look up | ||
| the operation body in the document registry or codebase. | ||
| - A partial _FQON_ may be used instead of a _document id_ as lookup keys in | ||
| static configuration files (e.g. alerting rules) in order to avoid duplication | ||
| and extra steps when an operation is updated (and thus, its _document id_). | ||
|
|
||
| ## Definition | ||
|
|
||
| FullyQualifiedOperationName :: OperationName : Project? : RepoFullName : Version | ||
|
|
||
| OperationName | ||
| : The _Name_ of the operation as declared on the _OperationDefinition_ node. | ||
|
|
||
| Project | ||
| : The identifier for the package or directory containing the operation. | ||
| : This is defined only for operations that live in a monorepo. | ||
|
|
||
| RepoFullName | ||
| : The full name of the Git repository (in the format of {"owner/repo"}). | ||
|
magicmark marked this conversation as resolved.
|
||
|
|
||
| Version | ||
| : A positive integer that increments each time the document body changes. | ||
|
magicmark marked this conversation as resolved.
|
||
| : The tuple of _OperationName_, _Project_ and _RepoFullName_ identifies a | ||
| document; the _Version_ part distinguishes its revisions. | ||
| : The _trusted document_ registry or other persistence layer must calculate or | ||
| store version numbers, starting at {1} and increasing monotonically. | ||
|
|
||
| **Examples** | ||
|
|
||
| A _Fully Qualified Operation Name_ with all parts: | ||
|
|
||
| ```example | ||
| GetHeaderData:styleguide:yelp/frontend:1 | ||
| ``` | ||
|
|
||
| A _Fully Qualified Operation Name_ which omits `Project` (i.e. | ||
| `petstore/website` is _not_ a monorepo, and has no concept of "projects"): | ||
|
|
||
| ```example | ||
| AllPets::petstore/website:1 | ||
| ``` | ||
|
|
||
| ## Partial Matches | ||
|
|
||
| Any _FQON_ part may be omitted to perform a partial match. | ||
|
|
||
| With the exception of omitting _Project_, partial matches must also omit the | ||
| `:Version` suffix. | ||
|
|
||
| The primary use case of this specification is to omit `:Version` for use as | ||
| lookup keys in static configuration files, as a way to target to all versions | ||
| of an operation. | ||
|
|
||
| **Examples** | ||
|
|
||
| | Pattern | Matches | | ||
| | --------------------------- | ------------------------------------------------------------------------------------------------------- | | ||
| | `GetFoo::` | All operations named {"GetFoo"} | | ||
| | `::bazcorp/qux` | All operations inside the {"bazcorp/qux"} Git repository | | ||
| | `GetFoo:barpkg:bazcorp/qux` | All operations named {"GetFoo"} inside the {"barpkg"} package inside the {"bazcorp/qux"} Git repository | | ||
|
|
||
| ## Security Considerations | ||
|
|
||
| It is recommended to avoid exposing FQONs in client code to avoid leaking | ||
| potentially sensitive internal repository names or project/directory names. | ||
|
|
||
| Clients should still send only the _document id_ over the wire, which is opaque. | ||
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| # GAP-7: Fully Qualified Operation Name (FQON) | ||
|
|
||
| Fully Qualified Operation Names (FQONs) are an alternate way to identify and | ||
| refer to GraphQL operations that provide both human readability and uniqueness | ||
| guarantees. | ||
|
|
||
| The primary motivation is to define a "lookup key" that may be used in static | ||
| configuration files (e.g. for alerting rules per operation) which correctly | ||
| targets operations, but without having to update the configuration each time a | ||
| _document id_ changes. | ||
|
|
||
| ## The problem | ||
|
|
||
| When using | ||
| [trusted documents](https://graphql.org/learn/security/#trusted-documents), we | ||
| may identify operations in two different ways: | ||
|
|
||
| 1. The "operation name" (e.g. `GetConsumerHeaderData`) | ||
| 2. The "document id" (e.g. `605fad0ee0a88...`) | ||
|
|
||
| _Operation names are not guaranteed to be unique_. | ||
|
|
||
| When using operation names, a developer might see `"GetUserInfo"` in service log, | ||
| copy and paste that string, use `git grep` and find it in the codebase -- only | ||
| to later discover it's the _wrong_ `GetUserInfo` query! | ||
|
|
||
| - Query names are only guaranteed to be unique with additional tooling. | ||
| - Even if tooling guarantees uniqueness within a repository, query names could | ||
| be reused in a _different_ repository — e.g. Web/iOS/Android code might | ||
| feasibly live in different Git repositories, and reuse operation names for | ||
| similar features. | ||
| - Additionally, servers may receive traffic for different versions of | ||
| the same query in order to support old mobile application installs - which | ||
| would share the same operation name. | ||
|
|
||
| Document IDs are unambiguous and may be used to solve this problem. However, | ||
| document IDs are not human friendly since they don't carry any semantic meaning, | ||
| which encourages developers to use document names in instead - which leads the | ||
| footgun outlined above. | ||
|
|
||
| Additionally, by definition, document IDs change each time the operation is | ||
| updated. If we use document IDs as lookup keys in an alerting configuration | ||
| file, this must be updated each time a new version of the query is published. | ||
| This creates duplication and a maintenance burden. | ||
|
|
||
| ## Solution | ||
|
|
||
| A _Fully Qualified Operation Name_ (FQON) is a human readable string that can | ||
| provide the same guarantees of uniqueness as document IDs, but and can be used | ||
| partially to omit the version number in such cases as alert config files. | ||
|
|
||
| **Example**: | ||
|
|
||
| ```yaml | ||
| # alert_thresholds.yaml | ||
| operations: | ||
| - fqon: GetFoo::bazcorp/qux | ||
| error_ratio: 0.3 | ||
| owner: myteam@example.com | ||
| - fqon: BarStuff::bazcorp/qux | ||
| error_ratio: 0.4 | ||
| alert: myteam@example.com | ||
| ``` | ||
|
|
||
| ## Definition | ||
|
|
||
| The format is: | ||
|
|
||
| ``` | ||
| name:project:repo:version | ||
| ``` | ||
|
|
||
| This is enough information to unambiguously identify the exact document | ||
| (assuming that client tooling guarantees no duplicate operation names per | ||
| project). | ||
|
|
||
| **Example**: | ||
|
|
||
| ``` | ||
| GetConsumerHeaderData:yelp-styleguide:yelp/frontend:3 | ||
| ``` | ||
|
|
||
| The right hand side components of the FQON can be omitted for a partial match: | ||
|
|
||
| **Example**: | ||
|
|
||
| ``` | ||
| GetConsumerHeaderData:yelp-styleguide:yelp/frontend | ||
| ``` | ||
|
|
||
| ^ this will match any version of the "same" query, and is recommended for use | ||
| as lookup keys in static configuration files | ||
|
|
||
| ### ARN Syntax | ||
|
|
||
| `:` as a separator is inspired by [ARNs](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html) |
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| id: 7 | ||
| title: "Fully Qualified Operation Names" | ||
| summary: > | ||
| A human-readable, unambiguous identifier for GraphQL operations. May be used | ||
| as lookup keys in static configuration files as an alternative to persisted | ||
| document IDs. | ||
| status: proposal | ||
| authors: | ||
| - name: "Mark Larah" | ||
| email: "markl@yelp.com" | ||
| githubUsername: "@magicmark" | ||
| sponsor: "@magicmark" | ||
| discussion: "https://github.com/graphql/gaps/pull/7" |
Oops, something went wrong.
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.
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.
Having
ProjectbeforeRepoFullNamebreaks my mental model a little bit. I understandProjectis for monorepos that may have several clients? Then I would prefer something more like so:So effectively, more like
This way it goes from general to specific.
Actually, thinking about this, why not even put the operation name at the end?
For someone using Maven Coordinates a lot, this would look a lot more familiar to me
Uh oh!
There was an error while loading. Please reload this page.
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.
++ yeah this ordering is a little weird, and an artifact of how we deployed this internally.
I wanted in theory for it to be ordered like a uri
"in order of decreasing significance from left to right"So that would imply
Which is the same ordering as your
bazcorp/qux/barpkg:GetFoo:1....however, when doing this internally, I wanted operation name to appear first, so I just yanked it 🤷.
Motivation is that when displayed in logs (grafana or splunk or whatever) or dashboard panels, a long FQON is likely to get truncated in the UI. By putting the op name first, there's more a guarantee you'll still see a difference in the value between rows for different operations. So I think there's some value and practicality here - but yes it does feel kinda weird as a pure uri.
Is that tradeoff worth it? Vote now!
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.
There was a similar discussion in the graphq-over-http working group.
For URLs, the last component of the path is highlighted/promoted by a lot of tooling like chrome devtools, etc...
Whether or not that applies here is an open question since those are not really part of a url. I'm not too familiar with grafana or splunk or whatever but aren't there any display options for custom fields?
Uh oh!
There was an error while loading. Please reload this page.
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.
do you know which other dev tools truncate the head and not the tail? is chrome an outlier or is the more popular way round? (thinking of tools like charles/proxyman/postman/wireshark etc etc that maybe mobile folks use more)
I've gone back and forth on this a lot trying to justify why
OperationNameshould be first, not last, but I don't have a super compelling reason beyond "it's what we already do (bunch of tooling built around this), folks are already used to it and I sill think it looks better", which is admittedly lazy :PThere 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.
I havent't done the research sadly, but will try to remember to post here when I find those!
Uh oh!
There was an error while loading. Please reload this page.
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.
Since it's not a clear slam dunk either way, I'm going to follow my gut on this one and merge as is. Unless you feel strongly enough otherwise.
I'm also open to switching it around in a future spec version if enough people feel strongly.