From 3b8c36da296b32ed1d2edec67c79bedf028a5b83 Mon Sep 17 00:00:00 2001 From: Maria Elisabeth Schreiber Date: Mon, 17 Jun 2024 12:10:13 -0600 Subject: [PATCH] docs: add enhanced operation signature config (#5466) --- docs/source/configuration/overview.mdx | 164 +++++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/docs/source/configuration/overview.mdx b/docs/source/configuration/overview.mdx index a14d850462..acc404c8f0 100644 --- a/docs/source/configuration/overview.mdx +++ b/docs/source/configuration/overview.mdx @@ -579,6 +579,170 @@ The default value of `experimental_parallelism` is `1`. In practice, you should tune `experimental_parallelism` based on metrics and benchmarks gathered from your router. + + +### Enhanced operation signature normalization + + + + + +Apollo's legacy operation signature algorithm removes information about certain fields, such as input objects and aliases. +This removal means some operations may have the same normalized signature though they are distinct operations. + +Beginning in v1.49.0, the router supports enhanced operation signature normalization. +Enhanced normalization incorporates [input types](#input-types) and [aliases](#aliases) in signature generation. +It also includes other improvements that make it more likely that two operations that only vary slightly have the same signature. + +Configure enhanced operation signature normalization in `router.yaml` with the `telemetry.apollo.experimental_apollo_signature_normalization_algorithm` option: + +```yaml title="router.yaml" +telemetry: + apollo: + experimental_apollo_signature_normalization_algorithm: enhanced # Default is legacy +``` + +Once you enable this configuration, operations with enhanced signatures appear with different operation IDs than they did previously in GraphOS Studio. + +#### Input types + +Enhanced signatures include input object type shapes, while still redacting any actual values. +Legacy signatures [replace input object type with `{}`](/graphos/metrics/operation-signatures/#1-transform-in-line-argument-values). + +Given the following example operation: + +```graphql showLineNumbers=false +query InlineInputTypeQuery { + inputTypeQuery( + input: { + inputString: "foo", + inputInt: 42, + inputBoolean: null, + nestedType: { someFloat: 4.2 }, + enumInput: SOME_VALUE_1, + nestedTypeList: [ { someFloat: 4.2, someNullableFloat: null } ], + listInput: [1, 2, 3] + } + ) { + enumResponse + } +} +``` + +The legacy normalization algorithm generates the following signature: + +```graphql showLineNumbers=false +query InlineInputTypeQuery { + inputTypeQuery(input: {}) { + enumResponse + } +} +``` + +The enhanced normalization algorithm generates the following signature: + +```graphql {3-11} showLineNumbers=false +query InlineInputTypeQuery { + inputTypeQuery( + input: { + inputString: "", + inputInt: 0, + inputBoolean: null, + nestedType: {someFloat: 0}, + enumInput: SOME_VALUE_1, + nestedTypeList: [{someFloat: 0, someNullableFloat: null}], + listInput: [] + } + ) { + enumResponse + } +} +``` + +#### Aliases + +Enhanced signatures include any field aliases used in an operation. +Legacy signatures [remove aliases completely](/graphos/metrics/operation-signatures/#field-aliases), meaning the signature may be invalid if the same field was used with multiple aliases. + +Given the following example operation: + +```graphql showLineNumbers=false +query AliasedQuery { + noInputQuery { + interfaceAlias1: interfaceResponse { + sharedField + } + interfaceAlias2: interfaceResponse { + ... on InterfaceImplementation1 { + implementation1Field + } + ... on InterfaceImplementation2 { + implementation2Field + } + } + inputFieldAlias1: objectTypeWithInputField(boolInput: true) { + stringField + } + inputFieldAlias2: objectTypeWithInputField(boolInput: false) { + intField + } + } +} +``` + +The legacy normalization algorithm generates the following signature: + +```graphql showLineNumbers=false +query AliasedQuery { + noInputQuery { + interfaceResponse { + sharedField + } + interfaceResponse { + ... on InterfaceImplementation1 { + implementation1Field + } + ... on InterfaceImplementation2 { + implementation2Field + } + } + objectTypeWithInputField(boolInput: true) { + stringField + } + objectTypeWithInputField(boolInput: false) { + intField + } + } +} +``` + +The enhanced normalization algorithm generates the following signature: + +```graphql showLineNumbers=false +query AliasedQuery { + noInputQuery { + interfaceAlias1: interfaceResponse { + sharedField + } + interfaceAlias2: interfaceResponse { + ... on InterfaceImplementation1 { + implementation1Field + } + ... on InterfaceImplementation2 { + implementation2Field + } + } + inputFieldAlias1: objectTypeWithInputField(boolInput: true) { + stringField + } + inputFieldAlias2: objectTypeWithInputField(boolInput: false) { + intField + } + } +} +``` + + ### Safelisting with persisted queries You can enhance your graph's security by maintaining a persisted query list (PQL), an operation safelist made by your first-party apps. As opposed to automatic persisted queries (APQ) where operations are automatically cached, operations must be preregistered to the PQL. Once configured, the router checks incoming requests against the PQL.