diff --git a/.gitignore b/.gitignore index f2ff697ba0..87c91a74ae 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,6 @@ # Previous git submodules dockerfiles/federation-demo dockerfiles/federation2-demo + +# macOS +.DS_Store \ No newline at end of file diff --git a/docs/shared/native-plugin-notice.mdx b/docs/shared/native-plugin-notice.mdx index 7d957b0d31..be0bcf185b 100644 --- a/docs/shared/native-plugin-notice.mdx +++ b/docs/shared/native-plugin-notice.mdx @@ -3,6 +3,6 @@ - Native plugins require familiarity with programming in Rust. - Native plugins require compiling a custom router binary from source, which can introduce unexpected behavior in your router that's difficult to diagnose and support. -Instead, for most router customizations, Apollo recommends creating either a [Rhai script](https://www.apollographql.com/docs/router/customizations/rhai/) or an [external coprocessor](https://www.apollographql.com/docs/router/customizations/coprocessor). Both of these customizations are supported by Apollo and provide strong separation of concerns and fault isolation. +Instead, for most router customizations, Apollo recommends creating either a [Rhai script](https://www.apollographql.com/docs/graphos/routing/customization/rhai/) or an [external coprocessor](https://www.apollographql.com/docs/router/customizations/coprocessor). Both of these customizations are supported by Apollo and provide strong separation of concerns and fault isolation. If you must create a native plugin, please [open a GitHub issue](https://github.com/apollographql/router/issues), and Apollo can investigate adding the custom capability to the stock router binary. diff --git a/docs/source/config.json b/docs/source/config.json index c0d464777e..8e481a369b 100644 --- a/docs/source/config.json +++ b/docs/source/config.json @@ -2,130 +2,16 @@ "title": "Self-Hosted Router", "algoliaFilters": ["docset:router"], "sidebar": { - "Introduction": "/", - "Quickstart": "/quickstart", - "Moving from @apollo/gateway": "/migrating-from-gateway", - "Federation Version Support": "/federation-version-support", - "Enterprise Features": ["/enterprise-features", ["enterprise"]], - "Configuring the Router": { - "Overview": "/configuration/overview", - "Caching": { - "In-Memory Caching": "/configuration/in-memory-caching", - "Distributed Caching": ["/configuration/distributed-caching", ["enterprise"]], - "Entity Caching": ["/configuration/entity-caching", ["enterprise", "preview"]] - }, - "Debugging": { - "Errors": "/errors", - "Telemetry": "/configuration/telemetry/overview", - "Subgraph Error Inclusion": "/configuration/subgraph-error-inclusion" - }, - "Networking": { - "Header Propagation": "/configuration/header-propagation", - "Traffic Shaping": "/configuration/traffic-shaping" - }, - "Security": { - "CORS": "/configuration/cors", - "CSRF Prevention": "/configuration/csrf", - "JWT Authentication": ["/configuration/authn-jwt", ["enterprise"]], - "Authorization": ["/configuration/authorization", ["enterprise"]], - "Subgraph Authentication": "/configuration/authn-subgraph", - "Operation Limits": [ - "/configuration/operation-limits", - [ - "enterprise" - ] - ], - "Safelisting with Persisted Queries": [ - "/configuration/persisted-queries", - [ - "enterprise" - ] - ], - "Demand Control" : [ - "/executing-operations/demand-control", - [ - "enterprise" - ] - ], - "Privacy and Data Collection": "/privacy" - } - }, - "Executing Operations": { - "Build and Run Queries": "/executing-operations/build-run-queries", - "@defer Support": "/executing-operations/defer-support", - "Request Format": "/executing-operations/requests", - "Query Batching": [ - "/executing-operations/query-batching", - [ - "enterprise" - ] - ], - "GraphQL Subscriptions": { - "Subscriptions Setup": ["/executing-operations/subscription-support", ["enterprise"]], - "Subgraph Protocol: HTTP Callback": [ - "/executing-operations/subscription-callback-protocol", - ["enterprise", "preview"] - ], - "Client Protocol: HTTP Multipart": ["/executing-operations/subscription-multipart-protocol", ["enterprise"]] - } + "Routing": { + "About Router": "/routing/about-router" }, - "Telemetry and Monitoring": { - "Overview": "/configuration/telemetry/overview", - "GraphOS Reporting": "/configuration/telemetry/apollo-telemetry", - "Client Awareness": "/managed-federation/client-awareness", - "Log Exporters": { - "Configuration": "/configuration/telemetry/exporters/logging/overview", - "Stdout": "/configuration/telemetry/exporters/logging/stdout" + "Reference": { + "Migration": { + "From Gateway": "/reference/migration/from-gateway" }, - "Metrics Exporters": { - "Configuration": "/configuration/telemetry/exporters/metrics/overview", - "Datadog": "/configuration/telemetry/exporters/metrics/datadog", - "Dynatrace": "/configuration/telemetry/exporters/metrics/dynatrace", - "New Relic": "/configuration/telemetry/exporters/metrics/new-relic", - "OTLP": "/configuration/telemetry/exporters/metrics/otlp", - "Prometheus": "/configuration/telemetry/exporters/metrics/prometheus" - }, - "Trace exporters": { - "Configuration": "/configuration/telemetry/exporters/tracing/overview", - "Datadog": "/configuration/telemetry/exporters/tracing/datadog", - "Dynatrace": "/configuration/telemetry/exporters/tracing/dynatrace", - "Jaeger": "/configuration/telemetry/exporters/tracing/jaeger", - "New Relic": "/configuration/telemetry/exporters/tracing/new-relic", - "OTLP": "/configuration/telemetry/exporters/tracing/otlp", - "Zipkin": "/configuration/telemetry/exporters/tracing/zipkin" - }, - "Instrumentation": { - "Instruments": "/configuration/telemetry/instrumentation/instruments", - "Events": "/configuration/telemetry/instrumentation/events", - "Conditions": "/configuration/telemetry/instrumentation/conditions", - "Spans": "/configuration/telemetry/instrumentation/spans", - "Selectors": "/configuration/telemetry/instrumentation/selectors", - "Standard Attributes": "/configuration/telemetry/instrumentation/standard-attributes", - "Standard Instruments": "/configuration/telemetry/instrumentation/standard-instruments" + "Router": { + "Configuration": "/reference/router/configuration" } - }, - "Containerization": { - "Overview": "/containerization/overview", - "Deploy on Kubernetes": "/containerization/kubernetes", - "Run with Docker": "/containerization/docker", - "Health Checks": "/configuration/health-checks" - }, - "Managed Federation": { - "Overview": "https://www.apollographql.com/docs/federation/managed-federation/overview", - "Setup": "https://www.apollographql.com/docs/federation/managed-federation/setup", - "GraphOS Studio Features": "https://www.apollographql.com/docs/graphos/graphs/federated-graphs" - }, - "Customizations": { - "Overview": "/customizations/overview", - "Rhai Scripts": "/customizations/rhai", - "Rhai API Reference": "/customizations/rhai-api", - "External Coprocessing": ["/customizations/coprocessor", ["enterprise"]], - "Native Rust Plugins": "/customizations/native", - "Custom Router Binary": "/customizations/custom-binary" - }, - "Subgraph Support": { - "Subgraph-Compatible Libraries": "https://www.apollographql.com/docs/federation/v2/other-servers/", - "Subgraph Specification": "https://www.apollographql.com/docs/federation/v2/federation-spec/" } } } diff --git a/docs/source/configuration/experimental_query_planner_mode.mdx b/docs/source/configuration/experimental_query_planner_mode.mdx deleted file mode 100644 index 67e1a2556d..0000000000 --- a/docs/source/configuration/experimental_query_planner_mode.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Experimental Query Planner Mode -subtitle: Switch between legacy and native query planning -noIndex: true ---- - -The router (GraphOS Router and Apollo Router Core) is in the early stages of -transitioning to a native query planner, replacing the existing legacy planner. - -As part of the efforts to ensure correctness and stability of the new planner, -v1.53.0 of the router enables both planners to run in parallel in order to -compare them. After the comparison, the router discards the native planner's results and -uses only the legacy planner to execute requests. - -The native planner uses a single thread in the cold path of the router. It has a -bounded queue of 10 queries. If the queue is full, the router simply does not run the -comparison to avoid excessive resource consumption. - -You can disable the native query planner by configuring your `router.yaml` to use just -`legacy` planning. You may want to disable it to avoid spikes in CPU utilization, for -example if an erroneous operation fails to complete planning in the native planner's -background thread. - -```yaml title="router.yaml" -experimental_query_planner_mode: legacy -``` - -The supported modes of `experimental_query_planner_mode` are the following: -* `new`. Enables only the native query planner. -* `both_best_effort` - default. Enables comparison between legacy and new native - query planners. The legacy query planner is used for execution. If any - unsupported features are detected, the router falls back to legacy with an - `info` log. -* `legacy`. Enables only the legacy query planner. diff --git a/docs/source/enterprise-features.mdx b/docs/source/enterprise-features.mdx index a6a1b53352..4691048016 100644 --- a/docs/source/enterprise-features.mdx +++ b/docs/source/enterprise-features.mdx @@ -31,10 +31,10 @@ For details on these features, see [this blog post](https://blog.apollographql.c To enable support for GraphOS Router Enterprise features: - Your organization must have a [GraphOS Enterprise plan](https://www.apollographql.com/pricing/). -- You must run GraphOS Router v1.12. [Download the latest version.](./quickstart#download-options) +- You must run GraphOS Router v1.12. [Download the latest version.](/router/quickstart#download-options) - Certain Enterprise features might require a later router version. See a particular feature's documentation for details. - Your router instances must connect to GraphOS with a **graph API key** and **graph ref** associated with your organization. - - You connect your router to GraphOS by setting [these environment variables](./configuration/overview/#environment-variables) when starting the router. + - You connect your router to GraphOS by setting [these environment variables](/router/configuration/overview/#environment-variables) when starting the router. - If your router _already_ connects to your GraphOS Enterprise organization, no further action is required. After enabling support, you can begin using all Enterprise features. Consult [the documentation for each feature](#list-of-features) to learn more. @@ -82,7 +82,7 @@ With an offline license, a router can either be fully disconnected from GraphOS -A router using an offline license requires [the use of local manifests](./configuration/persisted-queries/#experimental_local_manifests) when using [safelisting with persisted queries](./configuration/persisted-queries), otherwise it will not work as designed when the router is disconnected from Uplink. +A router using an offline license requires [the use of local manifests](/router/configuration/persisted-queries/#experimental_local_manifests) when using [safelisting with persisted queries](/router/configuration/persisted-queries), otherwise it will not work as designed when the router is disconnected from Uplink. @@ -100,9 +100,9 @@ Follow these steps to configure an GraphOS Router to use an offline Enterprise l 1. Provide the offline license to your router on startup. The router accepts an offline license in a few ways: - 1. [`--license `](./configuration/overview/#--license) CLI option, with an argument containing an absolute or relative path to an offline license file - 1. [`APOLLO_ROUTER_LICENSE_PATH`](./configuration/overview/#--license) environment variable, containing an absolute or relative path to an offline license file - 1. [`APOLLO_ROUTER_LICENSE`](./configuration/overview/#--license) environment variable, containing the stringified contents of an offline license file + 1. [`--license `](/router/configuration/overview/#--license) CLI option, with an argument containing an absolute or relative path to an offline license file + 1. [`APOLLO_ROUTER_LICENSE_PATH`](/router/configuration/overview/#--license) environment variable, containing an absolute or relative path to an offline license file + 1. [`APOLLO_ROUTER_LICENSE`](/router/configuration/overview/#--license) environment variable, containing the stringified contents of an offline license file @@ -113,11 +113,11 @@ Follow these steps to configure an GraphOS Router to use an offline Enterprise l 1. Configure the router to use a local supergraph schema by setting one of the following: - * [`--s/-supergraph`](./configuration/overview/#-s----supergraph) CLI option, with an argument containing an absolute or relative path to supergraph schema file - * [`APOLLO_SUPERGRAPH_PATH`](./configuration/overview/#-s----supergraph) environment variable, containing an absolute or relative path to supergraph schema file - * [`APOLLO_SUPERGRAPH_URLS`](./configuration/overview/#-s----supergraph) environment variable, containing URLs to supergraph schemas + * [`--s/-supergraph`](/router/configuration/overview/#-s----supergraph) CLI option, with an argument containing an absolute or relative path to supergraph schema file + * [`APOLLO_SUPERGRAPH_PATH`](/router/configuration/overview/#-s----supergraph) environment variable, containing an absolute or relative path to supergraph schema file + * [`APOLLO_SUPERGRAPH_URLS`](/router/configuration/overview/#-s----supergraph) environment variable, containing URLs to supergraph schemas -1. (**Recommended**) Configure the router to report usage metrics to GraphOS in a best-effort basis by setting both the [`APOLLO_KEY`](./configuration/overview/#apollo_key) and [`APOLLO_GRAPH_REF`](./configuration/overview#apollo_graph_ref) environment variables. +1. (**Recommended**) Configure the router to report usage metrics to GraphOS in a best-effort basis by setting both the [`APOLLO_KEY`](/router/configuration/overview/#apollo_key) and [`APOLLO_GRAPH_REF`](/router/configuration/overview#apollo_graph_ref) environment variables. These metrics are necessary for several important GraphOS features (operations checks, field insights, operation traces, contracts). Sending them best-effort incurs no performance or uptime penalties. @@ -168,7 +168,7 @@ These steps work both for running the router executable directly (`./router`) an ## Disabling Enterprise features -To disable an Enterprise feature, remove all of its associated configuration keys from your router's [YAML config file](./configuration/overview/#yaml-config-file). +To disable an Enterprise feature, remove all of its associated configuration keys from your router's [YAML config file](/router/configuration/overview/#yaml-config-file). ## Grace period for expired plans diff --git a/docs/source/executing-operations/build-run-queries.mdx b/docs/source/executing-operations/build-run-queries.mdx deleted file mode 100644 index 6303cab506..0000000000 --- a/docs/source/executing-operations/build-run-queries.mdx +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Build and Run Queries -subtitle: Use the Apollo Sandbox to build and run operations against your router -description: Use the Apollo Sandbox, a special mode of GraphOS Studio, to build and run GraphQL operations against your graph router. ---- - -The Apollo Router serves the following landing page from its base URL (`http://localhost:4000` by default): - -Apollo Router default landing page - -## Apollo Sandbox - -The landing page above provides a link to [Apollo Sandbox](https://studio.apollographql.com/sandbox), a powerful web IDE that enables you to build and run operations against your router. Sandbox is a special mode of [GraphOS Studio](https://www.apollographql.com/docs/studio/) that doesn't require an Apollo account. - -Apollo Sandbox diff --git a/docs/source/images/cloud-dedicated/add-a-subgraph.jpg b/docs/source/images/cloud-dedicated/add-a-subgraph.jpg new file mode 100644 index 0000000000..7f75526238 Binary files /dev/null and b/docs/source/images/cloud-dedicated/add-a-subgraph.jpg differ diff --git a/docs/source/images/cloud-dedicated/create-new-graph.jpg b/docs/source/images/cloud-dedicated/create-new-graph.jpg new file mode 100644 index 0000000000..249c9896d3 Binary files /dev/null and b/docs/source/images/cloud-dedicated/create-new-graph.jpg differ diff --git a/docs/source/images/cloud-dedicated/create-resource-share-final.jpg b/docs/source/images/cloud-dedicated/create-resource-share-final.jpg new file mode 100644 index 0000000000..6a2b5ce958 Binary files /dev/null and b/docs/source/images/cloud-dedicated/create-resource-share-final.jpg differ diff --git a/docs/source/images/cloud-dedicated/delete-network-associations.jpg b/docs/source/images/cloud-dedicated/delete-network-associations.jpg new file mode 100644 index 0000000000..daa7bae0d3 Binary files /dev/null and b/docs/source/images/cloud-dedicated/delete-network-associations.jpg differ diff --git a/docs/source/images/cloud-dedicated/delete-resource-share.jpg b/docs/source/images/cloud-dedicated/delete-resource-share.jpg new file mode 100644 index 0000000000..0e9dc8f7fa Binary files /dev/null and b/docs/source/images/cloud-dedicated/delete-resource-share.jpg differ diff --git a/docs/source/images/cloud-dedicated/graphos-service.jpg b/docs/source/images/cloud-dedicated/graphos-service.jpg new file mode 100644 index 0000000000..473f7d6376 Binary files /dev/null and b/docs/source/images/cloud-dedicated/graphos-service.jpg differ diff --git a/docs/source/images/cloud-dedicated/http-listener.jpg b/docs/source/images/cloud-dedicated/http-listener.jpg new file mode 100644 index 0000000000..183ee38fef Binary files /dev/null and b/docs/source/images/cloud-dedicated/http-listener.jpg differ diff --git a/docs/source/images/cloud-dedicated/insights-page.jpg b/docs/source/images/cloud-dedicated/insights-page.jpg new file mode 100644 index 0000000000..b113aca704 Binary files /dev/null and b/docs/source/images/cloud-dedicated/insights-page.jpg differ diff --git a/docs/source/images/cloud-dedicated/manage-capacity.jpg b/docs/source/images/cloud-dedicated/manage-capacity.jpg new file mode 100644 index 0000000000..d58ab78255 Binary files /dev/null and b/docs/source/images/cloud-dedicated/manage-capacity.jpg differ diff --git a/docs/source/images/cloud-dedicated/managed-permissions.jpg b/docs/source/images/cloud-dedicated/managed-permissions.jpg new file mode 100644 index 0000000000..15369112b8 Binary files /dev/null and b/docs/source/images/cloud-dedicated/managed-permissions.jpg differ diff --git a/docs/source/images/cloud-dedicated/register-targets.jpg b/docs/source/images/cloud-dedicated/register-targets.jpg new file mode 100644 index 0000000000..e062b3890c Binary files /dev/null and b/docs/source/images/cloud-dedicated/register-targets.jpg differ diff --git a/docs/source/images/cloud-dedicated/request-rate.jpg b/docs/source/images/cloud-dedicated/request-rate.jpg new file mode 100644 index 0000000000..485ab7d07b Binary files /dev/null and b/docs/source/images/cloud-dedicated/request-rate.jpg differ diff --git a/docs/source/images/cloud-dedicated/resource-principal.jpg b/docs/source/images/cloud-dedicated/resource-principal.jpg new file mode 100644 index 0000000000..ed80e5706d Binary files /dev/null and b/docs/source/images/cloud-dedicated/resource-principal.jpg differ diff --git a/docs/source/images/cloud-dedicated/resource-selection.jpg b/docs/source/images/cloud-dedicated/resource-selection.jpg new file mode 100644 index 0000000000..8e41770a7a Binary files /dev/null and b/docs/source/images/cloud-dedicated/resource-selection.jpg differ diff --git a/docs/source/images/cloud-dedicated/resource-share-summary.jpg b/docs/source/images/cloud-dedicated/resource-share-summary.jpg new file mode 100644 index 0000000000..03073f86f9 Binary files /dev/null and b/docs/source/images/cloud-dedicated/resource-share-summary.jpg differ diff --git a/docs/source/images/cloud-dedicated/service-identifiers.jpg b/docs/source/images/cloud-dedicated/service-identifiers.jpg new file mode 100644 index 0000000000..57855ea476 Binary files /dev/null and b/docs/source/images/cloud-dedicated/service-identifiers.jpg differ diff --git a/docs/source/images/cloud-dedicated/service-rules.jpg b/docs/source/images/cloud-dedicated/service-rules.jpg new file mode 100644 index 0000000000..6855a8cb41 Binary files /dev/null and b/docs/source/images/cloud-dedicated/service-rules.jpg differ diff --git a/docs/source/images/cloud-dedicated/target-group-configuration.jpg b/docs/source/images/cloud-dedicated/target-group-configuration.jpg new file mode 100644 index 0000000000..cde5a76df2 Binary files /dev/null and b/docs/source/images/cloud-dedicated/target-group-configuration.jpg differ diff --git a/docs/source/images/cloud-dedicated/vpc-lattice-access-logs.png b/docs/source/images/cloud-dedicated/vpc-lattice-access-logs.png new file mode 100644 index 0000000000..7bbe0a5c27 Binary files /dev/null and b/docs/source/images/cloud-dedicated/vpc-lattice-access-logs.png differ diff --git a/docs/source/images/cloud-dedicated/vpc-lattice-metrics.png b/docs/source/images/cloud-dedicated/vpc-lattice-metrics.png new file mode 100644 index 0000000000..5853d2dd20 Binary files /dev/null and b/docs/source/images/cloud-dedicated/vpc-lattice-metrics.png differ diff --git a/docs/source/images/cloud-dedicated/vpc-lattice-routing.png b/docs/source/images/cloud-dedicated/vpc-lattice-routing.png new file mode 100644 index 0000000000..b181e70150 Binary files /dev/null and b/docs/source/images/cloud-dedicated/vpc-lattice-routing.png differ diff --git a/docs/source/images/get-started/qp-dark.svg b/docs/source/images/get-started/qp-dark.svg new file mode 100644 index 0000000000..83b4402049 --- /dev/null +++ b/docs/source/images/get-started/qp-dark.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/images/get-started/qp.svg b/docs/source/images/get-started/qp.svg new file mode 100644 index 0000000000..acb4808d9c --- /dev/null +++ b/docs/source/images/get-started/qp.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/images/get-started/super-routing-1-dark.svg b/docs/source/images/get-started/super-routing-1-dark.svg new file mode 100644 index 0000000000..af4bc9a20e --- /dev/null +++ b/docs/source/images/get-started/super-routing-1-dark.svg @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/images/get-started/super-routing-1.svg b/docs/source/images/get-started/super-routing-1.svg new file mode 100644 index 0000000000..6c417ece8b --- /dev/null +++ b/docs/source/images/get-started/super-routing-1.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/images/get-started/super-routing-2-dark.svg b/docs/source/images/get-started/super-routing-2-dark.svg new file mode 100644 index 0000000000..45d85cdf75 --- /dev/null +++ b/docs/source/images/get-started/super-routing-2-dark.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/images/get-started/super-routing-2.svg b/docs/source/images/get-started/super-routing-2.svg new file mode 100644 index 0000000000..2ae570f87e --- /dev/null +++ b/docs/source/images/get-started/super-routing-2.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/images/get-started/super-routing-3-dark.svg b/docs/source/images/get-started/super-routing-3-dark.svg new file mode 100644 index 0000000000..cc6cea31d4 --- /dev/null +++ b/docs/source/images/get-started/super-routing-3-dark.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/images/get-started/super-routing-3.svg b/docs/source/images/get-started/super-routing-3.svg new file mode 100644 index 0000000000..78e84e9e5c --- /dev/null +++ b/docs/source/images/get-started/super-routing-3.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/source/images/initiating-endpoint.jpg b/docs/source/images/initiating-endpoint.jpg new file mode 100644 index 0000000000..b391c7d5aa Binary files /dev/null and b/docs/source/images/initiating-endpoint.jpg differ diff --git a/docs/source/images/router/cloud-router-configuration.jpg b/docs/source/images/router/cloud-router-configuration.jpg new file mode 100644 index 0000000000..b14986e31a Binary files /dev/null and b/docs/source/images/router/cloud-router-configuration.jpg differ diff --git a/docs/source/images/router/cloud-router-details.jpg b/docs/source/images/router/cloud-router-details.jpg new file mode 100644 index 0000000000..965810919b Binary files /dev/null and b/docs/source/images/router/cloud-router-details.jpg differ diff --git a/docs/source/images/router/cloud-router-region-ord.jpg b/docs/source/images/router/cloud-router-region-ord.jpg new file mode 100644 index 0000000000..ff8ec6bef3 Binary files /dev/null and b/docs/source/images/router/cloud-router-region-ord.jpg differ diff --git a/docs/source/images/router/router-endpoint.jpg b/docs/source/images/router/router-endpoint.jpg new file mode 100644 index 0000000000..bb341ecae0 Binary files /dev/null and b/docs/source/images/router/router-endpoint.jpg differ diff --git a/docs/source/index.mdx b/docs/source/index.mdx deleted file mode 100644 index 3ad0bb4e8f..0000000000 --- a/docs/source/index.mdx +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: Self-Hosted Router -subtitle: High-performance routing with self-hosted supergraph runtimes -description: Distribute operations efficiently across microservices in your federated GraphQL API with the Apollo GraphOS Router or Apollo Router Core. Configure caching, security features, and more. ---- - -import { Link } from 'gatsby'; - - - -> 💡 Not self-hosting your router? Get started with [Cloud Router](/graphos/quickstart/cloud/). - -GraphOS Router is a scalable runtime for supergraphs that's fully integrated with GraphOS and based on the Apollo Router Core. - -A self-hosted GraphOS Router or Apollo Router Core enables full management of your supergraph runtime infrastructure and deployments. - -```mermaid -flowchart LR; - clients(Clients); - subgraph "Your infrastructure"; - router(["Router"]); - serviceB[Products
API]; - serviceC[Reviews
API]; - router -->|Sub-query| serviceB & serviceC; - end; - clients -.->|Query| router; - class clients secondary; -``` - -The router intelligently distributes inbound queries across your GraphQL-powered microservices, enabling clients to fetch data from multiple sources with a single request. - -> Learn about the [distinction between the router and an API gateway](/technotes/TN0037-api-gateways/). - - -If you have an existing federated graph that currently uses `@apollo/gateway`, you can move to the router without changing any other part of your graph. - -

- - -

- -> **This documentation helps you run a _self-hosted_ instance of a router.** If you [create a cloud supergraph](/graphos/quickstart/cloud/) with Apollo GraphOS, Apollo provisions and hosts a GraphOS Router for you. -> -> Cloud supergraphs are recommended for organizations that don't need to host their router in their own infrastructure. - - -## Features - -- Full support for [Apollo Federation](/federation/) and supergraph management via [GraphOS](/graphos/) -- Extensive declarative [configuration options](./configuration/overview) (header propagation, CORS settings, OpenTelemetry support, and more) -- Support for [scripting](./customizations/rhai/) via the Rhai scripting language -- Advanced [GraphOS Enterprise features](./enterprise-features), including: - - Real-time data via [GraphQL subscriptions](./executing-operations/subscription-support/) - - [JWT authentication](./configuration/authn-jwt) - - [Distributed caching](./configuration/distributed-caching/) for multi-router fleets - - Customization in any language via [external coprocessing](./customizations/coprocessor/) - - [Operation limits](./configuration/operation-limits/) diff --git a/docs/source/privacy.mdx b/docs/source/privacy.mdx deleted file mode 100644 index 5d675f8779..0000000000 --- a/docs/source/privacy.mdx +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Privacy and Data Collection -subtitle: Learn what data the router collects and how to opt out -description: Learn what data the Apollo GraphOS Router and Apollo Router Core collect and how to opt out. By default, the router collects anonymous usage data to help improve the product. ---- - -By default, the GraphOS Router or Apollo Router Core collects anonymous usage data to help us improve the product. - -The router doesn't collect any personally identifiable information such as API keys, graph names, or file paths. - - - -**To opt out of data collection,** set the `APOLLO_TELEMETRY_DISABLED` environment variable to `true` in each environment where you run the router. - - - -For more information on how this data is collected and used, see [Apollo's privacy policy](https://www.apollographql.com/privacy-policy/). - -## Collected data - -Unless you opt out, the router reports the following data: - -- The execution command that was run _(excluding any identifiable arguments such as file-system paths or profile names)_ -- The version of `router` that was executed -- The configuration properties which have been referenced, but limited to types which could not contain personally identifiable information (e.g., certain scalar types; a property which is set to `true` not the value if it is a `string`) -- A unique, anonymized **machine identifier**, which is the same for every command run on the same machine -- A unique, anonymized **session identifier**, which is different for every command -- The SHA-256 hash of the directory that `router` was executed from -- The SHA-256 hash of the contents of the supergraph schema -- The operating system `router` was executed on -- The CI system `router` was executed on, if any diff --git a/docs/source/reference/graphos-features.mdx b/docs/source/reference/graphos-features.mdx new file mode 100644 index 0000000000..129e790afa --- /dev/null +++ b/docs/source/reference/graphos-features.mdx @@ -0,0 +1,177 @@ +--- +title: GraphOS Router Features +subtitle: Use router features enabled by GraphOS and the Enterprise plan +description: Unlock Enterprise features for the GraphOS Router by connecting it to Apollo GraphOS. +redirectFrom: + - /router/enterprise-features +--- + +A router connected to GraphOS, whether cloud-hosted or self-hosted, is called a **GraphOS Router**. It has access to specific GraphOS features depending on the connected GraphOS organization's plan. Refer to the [pricing page](https://www.apollographql.com/pricing#graphos-router) to compare GraphOS Router features across plan types. + +## GraphOS Router features + + + +For details on these features, see [this blog post](https://blog.apollographql.com/apollo-router-v1-12-improved-router-security-performance-and-extensibility) in addition to the documentation links above. + +## Enterprise plan features + + + +Try the Enterprise features of GraphOS Router with a free [GraphOS trial](https://www.apollographql.com/pricing). + + + +To enable support for Enterprise features in GraphOS Router: + +- Your organization must have a [GraphOS Enterprise plan](https://www.apollographql.com/pricing/). +- You must run GraphOS Router v1.12 or later. [Download the latest version.](/graphos/reference/router/self-hosted-install#1-download-and-extract-the-router-binary) + - Certain Enterprise features might require a later router version. See a particular feature's documentation for details. +- Your router instances must connect to GraphOS with a **graph API key** and **graph ref** associated with your organization. + - You connect your router to GraphOS by setting [these environment variables](/graphos/reference/router/configuration#environment-variables) when starting the router. + - If your router _already_ connects to your GraphOS Enterprise organization, no further action is required. + +After enabling support, you can begin using all [Enterprise features](#graphos-router-features). + +### The Enterprise license + +Whenever your router instance starts up and connects to GraphOS, it fetches a **license**, which is the credential that authorizes its use of Enterprise features: + +```mermaid +flowchart LR; + subgraph "Your Infrastructure"; + router(["GraphOS Router"]); + end; + subgraph "GraphOS"; + uplink(Apollo Uplink) + end; + router--"Fetches supergraph schema
and license"-->uplink; +``` + +A router instance retains its license for the duration of its execution. If you stop a router instance and then later start a new instance on the same machine, it must fetch a new license. + +Licenses are served via [Apollo Uplink](/graphos/routing/uplink), the same multi-cloud endpoint that your router uses to fetch its supergraph schema from GraphOS. Because of this, licenses introduce no additional network dependencies, meaning your router's uptime remains unaffected. To learn more about multi-cloud Uplink, read the [Apollo blog post](https://www.apollographql.com/blog/announcement/backend/introducing-multi-cloud-support-for-apollo-uplink). + +A router instance's license is valid for the duration of your organization's current subscription billing period (plus a [grace period](#grace-period-for-expired-plans)), even if the router temporarily becomes disconnected from GraphOS. + + + +### Offline Enterprise license + + + + + +Offline Enterprise license support is available on an as-needed basis. Send a request to your Apollo contact to enable it for your GraphOS Studio organization. + + + +Running your GraphOS Router fleet while fully connected to GraphOS is the best choice for most Apollo users. However, some scenarios can prevent your routers from connecting to GraphOS for an extended period, ranging from disasters that break connectivity to isolated sites operating with air-gapped networks. If you need to restart or rapidly scale your entire router fleet, but you're unable to communicate with Apollo Uplink, new router instances won't be able to serve traffic. + +To support long-term disconnection scenarios, GraphOS supports **offline Enterprise licenses** for the GraphOS Router. An offline license enables routers to start and serve traffic without a persistent connection to GraphOS. The functionality available with an offline license is much like being fully connected to GraphOS, including the GraphOS [schema delivery pipeline](/graphos/platform/schema-management#schema-delivery) for supergraph CI (schema checks, linting, contracts, etc.). + +An offline license can be retrieved from GraphOS with the [`rover license fetch`](/rover/commands/license) command. + +With an offline license, a router can either be fully disconnected from GraphOS or configured to connect to GraphOS on a best-effort basis so that it can send graph usage metrics. Apollo recommends configuring your router to report graph usage metrics to GraphOS whenever possible. Since your router sends metrics in a best-effort fashion, it incurs no performance or uptime penalties while enabling several powerful GraphOS features, such as operation checks, field insights, operation traces, and contracts. + + + +A router using an offline license requires [the use of local manifests](/graphos/routing/security/persisted-queries#experimental_local_manifests) when using [safelisting with persisted queries](/graphos/routing/security/persisted-queries), otherwise it will not work as designed when the router is disconnected from Uplink. + + + +An offline license is valid for the lesser of the duration of your contract with Apollo, or one year, with an added grace period of 28 days. You are responsible for keeping your offline license files up to date within your infrastructure by rerunning `rover license fetch` to fetch updated license files. + +#### Set up offline license for the GraphOS Router + +Follow these steps to configure an GraphOS Router to use an offline Enterprise license: + +1. Fetch an offline license by running [`rover license fetch`](/rover/commands/license/#license-fetch) with the ID of the graph from which you want to fetch a license: + + ```bash + rover license fetch --graph-id + ``` + +1. Provide the offline license to your router on startup. The router accepts an offline license in a few ways: + + 1. [`--license `](/graphos/reference/router/configuration#--license) CLI option, with an argument containing an absolute or relative path to an offline license file + 1. [`APOLLO_ROUTER_LICENSE_PATH`](/graphos/reference/router/configuration#--license) environment variable, containing an absolute or relative path to an offline license file + 1. [`APOLLO_ROUTER_LICENSE`](/graphos/reference/router/configuration#--license) environment variable, containing the stringified contents of an offline license file + + + + - The router checks the CLI option and environment variables in the listed order, then it uses the value of the first option or variable that is set. + - The `--license ` option is only available when running the router binary. When running a router with `rover dev`, you must use environment variables to provide your offline license. + + + +1. Configure the router to use a local supergraph schema by setting one of the following: + + * [`--s/-supergraph`](/graphos/reference/router/configuration#-s----supergraph) CLI option, with an argument containing an absolute or relative path to supergraph schema file + * [`APOLLO_SUPERGRAPH_PATH`](/graphos/reference/router/configuration#-s----supergraph) environment variable, containing an absolute or relative path to supergraph schema file + * [`APOLLO_SUPERGRAPH_URLS`](/graphos/reference/router/configuration#-s----supergraph) environment variable, containing URLs to supergraph schemas + +1. (**Recommended**) Configure the router to report usage metrics to GraphOS in a best-effort basis by setting both the [`APOLLO_KEY`](/graphos/reference/router/configuration#apollo_key) and [`APOLLO_GRAPH_REF`](/graphos/reference/router/configuration#apollo_graph_ref) environment variables. + + These metrics are necessary for several important GraphOS features (operations checks, field insights, operation traces, contracts). Sending them best-effort incurs no performance or uptime penalties. + +### Licenses with local development + +You might also need to run an GraphOS Router instance on your local machine, such as with the [`rover dev`](/graphos/graphs/local-development) command. It's likely that your local router instance doesn't connect to GraphOS to get its supergraph schema from Uplink. For example, you can run `rover dev` to perform composition locally. + +**You _can_ use Enterprise router features with a locally composed supergraph schema!** To do so, your router must still connect to GraphOS to obtain its [license](#the-enterprise-license). + +#### Set up local development + +These steps work both for running the router executable directly (`./router`) and for running it via `rover dev`: + +1. [Create a new variant](/graphos/graphs/federated-graphs/#adding-a-variant-via-the-rover-cli) for your supergraph that you'll use _only_ to fetch Enterprise licenses. + - Give the variant a name that clearly distinguishes it from variants that track schemas and metrics. + - Every team member that runs a router locally can use this same variant. + - When you create this variant, publish a dummy subgraph schema like the following (your router won't use it): + + ```graphql + type Query { + hello: String + } + ``` + +2. Create a [graph API key](/graphos/platform/access-management/api-keys#graph-api-keys) for your supergraph and assign it the **Contributor** role. + - We recommend creating a separate graph API key for _each team member_ that will run the router locally. + +3. When you start up your local router with your usual command, set the `APOLLO_GRAPH_REF` and `APOLLO_KEY` environment variables for that command: + + ```bash + APOLLO_GRAPH_REF="..." APOLLO_KEY="..." ./router --supergraph schema.graphql + ``` + + - The value of `APOLLO_GRAPH_REF` is the graph ref for the new, license-specific variant you created (for example, `docs-example-graph@local-licenses`). + - The value of `APOLLO_KEY` is the graph API key you created. + +4. Your router will fetch an Enterprise license while using its locally composed supergraph schema. + +### Common errors + +**If your router doesn't successfully connect to GraphOS,** it logs an error that begins with one of the following strings if any Enterprise features are enabled: + +| Error Message | Description | +|-----------------------------|-------------| +| `Not connected to GraphOS.` | At least one of the `APOLLO_KEY` and `APOLLO_GRAPH_REF` environment variables wasn't set on router startup. | +| `License not found.` | The router connected to GraphOS with credentials that are not associated with a GraphOS Enterprise plan. | +| `License has expired.` | Your organization's GraphOS Enterprise subscription has ended. **Your router will stop processing incoming requests at the end of the standard [grace period](#grace-period-for-expired-plans).** | + +## Turning off Enterprise features + +To turn off an Enterprise feature, remove all of its associated configuration keys from your router's [YAML config file](/graphos/reference/router/configuration#yaml-config-file). + +## Grace period for expired plans + +If your organization terminates its GraphOS Enterprise subscription, your router's Enterprise license is considered expired at the end of your final paid subscription period. GraphOS provides a grace period for expired licenses so that you can turn off Enterprise features before they produce breaking errors in your router. + +If your router has an expired Enterprise license, its behavior degrades according to the following schedule, _if_ any Enterprise features are still enabled: + +- **For the first 14 days after your license expires,** your router continues to behave as though it has a valid license. +- **After 14 days,** your router begins a **soft outage**: it continues processing client requests, but it emits logs and metrics that indicate it's experiencing an outage. +- **After 28 days,** your router begins a **hard outage**. It no longer processes incoming client requests and continues emitting logs and metrics from the soft outage. + +Your router resumes normal functioning whenever you renew your GraphOS Enterprise subscription or turn off all [Enterprise features](#list-of-features). diff --git a/docs/source/migrating-from-gateway.mdx b/docs/source/reference/migration/from-gateway.mdx similarity index 85% rename from docs/source/migrating-from-gateway.mdx rename to docs/source/reference/migration/from-gateway.mdx index 4ae7ae2bed..e1fa6222a3 100644 --- a/docs/source/migrating-from-gateway.mdx +++ b/docs/source/reference/migration/from-gateway.mdx @@ -4,19 +4,13 @@ subtitle: Migrating to the router from @apollo/gateway description: Learn how to migrate a federated graph from @apollo/gateway to the Apollo GraphOS Router or Apollo Router Core without any changes to your subgraphs. --- - - Learn how to migrate a federated supergraph using the `@apollo/gateway` library to the GraphOS Router or Apollo Router Core and gain significant performance improvements while making zero changes to your subgraphs. ## What's different? Whereas `@apollo/gateway` is an npm package, the router is packaged as a _static, standalone binary_. -The router exposes the most common critical features via declarative configuration. You customize the router with a [YAML configuration file](./configuration/overview/#yaml-config-file) that takes effect at startup. Configurations can be modified and take effect without restart if you either start the router with the `--hot-reload` flag or set the `APOLLO_ROUTER_HOT_RELOAD` environment variable to `true`. +The router exposes the most common critical features via declarative configuration. You customize the router with a [YAML configuration file](/router/configuration/overview/#yaml-config-file) that takes effect at startup. Configurations can be modified and take effect without restart if you either start the router with the `--hot-reload` flag or set the `APOLLO_ROUTER_HOT_RELOAD` environment variable to `true`. Although you _can_ download the Apollo Router Core source and use it as a library in a larger project and as the basis for a self-hosted GraphOS Router, you may not need to because the features that were implemented by custom code with `@apollo/gateway` may be standard, supported features of the router. @@ -85,9 +79,9 @@ The [`buildService` function](/apollo-server/using-federation/api/apollo-gateway Common use cases include: * Overriding subgraph URLs at runtime - * In the router, you can use the [`override_subgraph_urls` option](./configuration/overview#subgraph-routing-urls). + * In the router, you can use the [`override_subgraph_urls` option](/router/configuration/overview#subgraph-routing-urls). * Propagating headers to subgraphs via `RemoteGraphQLDataSource` - * In the router, you can use the [`headers` option](./configuration/header-propagation). + * In the router, you can use the [`headers` option](/graphos/routing/header-propagation). ### `logger` @@ -95,7 +89,7 @@ The [`logger` constructor option](/apollo-server/using-federation/api/apollo-gat In the router, logging is JSON-structured in production environments by default, and you can adjust the verbosity. More advanced logging can be enabled through the use of [plugins](#plugins). -For more information, see [Logging in the router](./configuration/logging/). +For more information, see [Logging in the router](/router/configuration/telemetry/exporters/logging/overview). ## `ApolloServer` constructor options @@ -113,13 +107,13 @@ This constructor option is an object that enables you to propagate information a * Authentication information * Header propagation -The router provides [similar functionality](./customizations/rhai-api#requestcontext). +The router provides [similar functionality](/graphos/reference/router/rhai#requestcontext). ### `plugins` This constructor option is an array of built-in or custom `plugins` that extend Apollo Server's functionality. If you provide `plugins` to your `ApolloServer` instance, take note of each plugin's functionality and add it to your migration checklist. -Before you attempt to replicate a plugin's functionality via a router [customization](#supported-customizations), check whether any router [configuration options](./configuration/overview/) provide that same functionality. For example, the router supports options for propagating HTTP headers to subgraphs and enabling OpenTelemetry instrumentation. +Before you attempt to replicate a plugin's functionality via a router [customization](#supported-customizations), check whether any router [configuration options](/router/configuration/overview/) provide that same functionality. For example, the router supports options for propagating HTTP headers to subgraphs and enabling OpenTelemetry instrumentation. If one of your `@apollo/gateway` plugins _does_ require a corresponding router customization, we encourage you to describe your use case in the router repo's [GitHub discussions](https://github.com/apollographql/router/discussions/). It might represent core functionality that the router _should_ provide out of the box, and we can help discuss the design. @@ -129,21 +123,21 @@ For less common use cases, we also want to help build an ecosystem of shared cus The router supports two types of customizations that hook into the request-handling pipeline: -* [Rhai scripts](./customizations/rhai/) +* [Rhai scripts](/graphos/routing/customization/rhai/) * Rhai is a scripting language designed for use with Rust applications. -* [External coprocessing](./customizations/coprocessor/) +* [External coprocessing](/router/customizations/coprocessor/) Examples for each are provided in their respective documentation, and in the [Router repo](https://github.com/apollographql/router/tree/main/examples). ## Kubernetes deployment -For migrating to the router deployed on Kubernetes, see some tips for [configuring your router deployment](./containerization/kubernetes/#configure-for-migration-from-gateway). +For migrating to the router deployed on Kubernetes, see some tips for [configuring your router deployment](/router/containerization/kubernetes/#configure-for-migration-from-gateway). ## Responses and errors Apollo Gateway runs its core GraphQL server using Apollo Server and a user configured HTTP server. GraphOS Router is built as an all-in-one product with the GraphQL and HTTP server bundled together. With this change there may be some slight difference to the logic of HTTP status codes or GraphQL error extension codes. -Refer the full list of [router error codes](./errors) for any changes to your gateway implementation. If you need to customize the responses, refer to [router customizations](./customizations/overview). +Refer the full list of [router error codes](/router/errors) for any changes to your gateway implementation. If you need to customize the responses, refer to [router customizations](/router/customizations/overview). ## Reporting migration issues diff --git a/docs/source/migrating-from-version-0.x.mdx b/docs/source/reference/migration/from-router-version-0.x.mdx similarity index 88% rename from docs/source/migrating-from-version-0.x.mdx rename to docs/source/reference/migration/from-router-version-0.x.mdx index 11589821d6..af1dcec1df 100644 --- a/docs/source/migrating-from-version-0.x.mdx +++ b/docs/source/reference/migration/from-router-version-0.x.mdx @@ -15,7 +15,7 @@ Our pre-1.0 versions of the router had highly iterative development lifecycles a - Rhai scripting capabilities - the exposed API -In most cases, things have been moved around in order to strike the right balanace of user experience and functionality without over-exposing things that we'd like to still design further. +In most cases, things have been moved around in order to strike the right balance of user experience and functionality without over-exposing things that we'd like to still design further. The changes you'll need to make depend on which version you were coming from. The key versions before 1.0 included: @@ -46,7 +46,7 @@ In addition, the following command line flags have changed: Removed --apollo-graph-key and --apollo-graph-ref -Unlike `@apollo/gateway`, the Apollo Router Core is packaged as a _static, standalone binary_. To customize its behavior, you pass it a [YAML configuration file](./configuration/overview/#yaml-config-file) at startup. If you start the router with the `--hot-reload` flag (or set the `APOLLO_ROUTER_HOT_RELOAD` environment variable to `true`), you can even modify that configuration without a restart. +Unlike `@apollo/gateway`, the Apollo Router Core is packaged as a _static, standalone binary_. To customize its behavior, you pass it a [YAML configuration file](/router/configuration/overview/#yaml-config-file) at startup. If you start the router with the `--hot-reload` flag (or set the `APOLLO_ROUTER_HOT_RELOAD` environment variable to `true`), you can even modify that configuration without a restart. You _can_ download the router source and use it as a library in a larger project. However, our goal is to remove the need to write custom code in your graph router (which is always necessary with `@apollo/gateway`). Instead, the router exposes the most common critical features via declarative configuration. @@ -115,9 +115,9 @@ The [`buildService` function](/apollo-server/using-federation/api/apollo-gateway Common use cases include: * Overriding subgraph URLs at runtime - * In the router, you can use the [`override_subgraph_urls` option](./configuration/overview#subgraph-routing-urls). + * In the router, you can use the [`override_subgraph_urls` option](/router/configuration/overview#subgraph-routing-urls). * Propagating headers to subgraphs via `RemoteGraphQLDataSource` - * In the router, you can use the [`headers` option](./configuration/header-propagation). + * In the router, you can use the [`headers` option](/graphos/routing/header-propagation). ### `logger` @@ -125,7 +125,7 @@ The [`logger` constructor option](/apollo-server/using-federation/api/apollo-gat In the router, logging is JSON-structured in production environments by default, and you can adjust the verbosity. More advanced logging can be enabled through the use of [plugins](#plugins). -For more information, see [Logging in the router](./configuration/logging/). +For more information, see [Logging in the router](/router/configuration/telemetry/exporters/logging/overview). ## `ApolloServer` constructor options @@ -143,13 +143,13 @@ This constructor option is an object that enables you to propagate information a * Authentication information * Header propagation -The router provides [similar functionality](./customizations/rhai-api/#requestcontext). +The router provides [similar functionality](/graphos/reference/router/rhai/#requestcontext). ### `plugins` This constructor option is an array of built-in or custom `plugins` that extend Apollo Server's functionality. If you provide `plugins` to your `ApolloServer` instance, take note of each plugin's functionality and add it to your migration checklist. -Before you attempt to replicate a plugin's functionality via a router [customization](#supported-customizations), check whether any router [configuration options](./configuration/overview/) provide that same functionality. For example, the router supports options for propagating HTTP headers to subgraphs and enabling OpenTelemetry instrumentation. +Before you attempt to replicate a plugin's functionality via a router [customization](#supported-customizations), check whether any router [configuration options](/router/configuration/overview/) provide that same functionality. For example, the router supports options for propagating HTTP headers to subgraphs and enabling OpenTelemetry instrumentation. > If one of your `@apollo/gateway` plugins _does_ require a corresponding router customization, we encourage you to describe your use case in the router repo's [GitHub discussions](https://github.com/apollographql/router/discussions/). It might represent core functionality that the router _should_ provide out of the box, and we can help discuss the design. > @@ -159,10 +159,10 @@ Before you attempt to replicate a plugin's functionality via a router [customiza The router currently supports two types of customizations that hook into the request-handling pipeline: -* [Rhai scripts](./customizations/rhai/) +* [Rhai scripts](/graphos/routing/customization/rhai/) * Rhai is a scripting language designed for use with Rust applications. -* [External coprocessing](./customizations/coprocessor/). - * Requires a [GraphOS Router with an Enterprise plan](./enterprise-features). +* [External coprocessing](/router/customizations/coprocessor/). + * Requires a [GraphOS Router with an Enterprise plan](/router/enterprise-features). Examples for each are provided in their respective documentation, and in the [Router repo](https://github.com/apollographql/router/tree/main/examples). diff --git a/docs/source/configuration/overview.mdx b/docs/source/reference/router/configuration.mdx similarity index 85% rename from docs/source/configuration/overview.mdx rename to docs/source/reference/router/configuration.mdx index 7f7c4a675a..3c89326a73 100644 --- a/docs/source/configuration/overview.mdx +++ b/docs/source/reference/router/configuration.mdx @@ -4,8 +4,6 @@ subtitle: Configure a router via environment variables, command-line options, an description: Learn how to configure the Apollo GraphOS Router or Apollo Router Core with environment variables, command-line options and commands, and YAML configuration files. --- -import RedisTLS from '../../shared/redis-tls.mdx' - Learn how to customize the behavior of your GraphOS Router or Apollo Router Core with environment variables, command-line commands and options, and YAML file configuration. ## Environment variables @@ -76,7 +74,7 @@ A path to a file containing the [graph API key](/graphos/api-keys/#graph-api-key ## Command-line options -After [installing the Apollo Router Core](../quickstart/) in your current working directory, you can run the router with the following example command: +After [installing the Apollo Router Core](/router/quickstart) in your current working directory, you can run the router with the following example command: ```bash ./router --config router.yaml --supergraph supergraph-schema.graphql @@ -104,13 +102,13 @@ This reference lists and describes the options supported by the `router` binary. -The [supergraph schema](/federation/federated-types/overview/#supergraph-schema) of a router. Specified by absolute or relative path (`-s` / `--supergraph `, or `APOLLO_ROUTER_SUPERGRAPH_PATH`), or a comma-separated list of URLs (`APOLLO_ROUTER_SUPERGRAPH_URLS`). +The [supergraph schema](/federation/federated-types/overview#supergraph-schema) of a router. Specified by absolute or relative path (`-s` / `--supergraph `, or `APOLLO_ROUTER_SUPERGRAPH_PATH`), or a comma-separated list of URLs (`APOLLO_ROUTER_SUPERGRAPH_URLS`). > 💡 Avoid embedding tokens in `APOLLO_ROUTER_SUPERGRAPH_URLS` because the URLs may appear in log messages. Setting this option disables polling from Apollo Uplink to fetch the latest supergraph schema. -To learn how to compose your supergraph schema with the Rover CLI, see the [Federation quickstart](/federation/quickstart/local-composition/). +To learn how to compose your supergraph schema with the Rover CLI, see the [Federation quickstart](/federation/quickstart). **Required** if you are _not_ using managed federation. If you _are_ using managed federation, you may need to set this option when following [advanced deployment workflows](/federation/managed-federation/deployment/#advanced-deployment-workflows). @@ -212,9 +210,9 @@ An offline GraphOS Enterprise license. Enables Enterprise router features when d An offline license is specified either as an absolute or relative path to a license file (`--license ` or `APOLLO_ROUTER_LICENSE_PATH`), or as the stringified contents of a license (`APOLLO_ROUTER_LICENSE`). -When not set, the router retrieves an Enterprise license [from GraphOS via Apollo Uplink](../enterprise-features/#the-enterprise-license). +When not set, the router retrieves an Enterprise license [from GraphOS via Apollo Uplink](/router/enterprise-features/#the-enterprise-license). -For information about fetching an offline license and configuring the router, see [Offline Enterprise license](../enterprise-features/#offline-enterprise-license). +For information about fetching an offline license and configuring the router, see [Offline Enterprise license](/router/enterprise-features/#offline-enterprise-license). @@ -501,9 +499,9 @@ supergraph: ### Debugging -- To configure logging, see [Logging in the router](./telemetry/exporters/logging/overview). +- To configure logging, see [Logging in the router](/router/configuration/telemetry/exporters/logging/overview). -- To configure the inclusion of subgraph errors, see [Subgraph error inclusion](./subgraph-error-inclusion). +- To configure the inclusion of subgraph errors, see [Subgraph error inclusion](/router/configuration/subgraph-error-inclusion). ### Landing pages @@ -563,7 +561,7 @@ In this example, the `organizations` subgraph URL is overridden to point to `htt Any subgraphs that are _omitted_ from `override_subgraph_url` continue to use the routing URL specified in the supergraph schema. -If you need to override the subgraph URL at runtime on a per-request basis, you can use [request customizations](../customizations/overview/#request-path) in the `SubgraphService` layer. +If you need to override the subgraph URL at runtime on a per-request basis, you can use [request customizations](/router/customizations/overview/#request-path) in the `SubgraphService` layer. ### Caching @@ -573,11 +571,38 @@ By default, the router stores the following data in its in-memory cache to impro - Automatic persisted queries (APQ) - Introspection responses -You can configure certain caching behaviors for generated query plans and APQ (but not introspection responses). For details, see [In-Memory Caching in the router](./in-memory-caching/). +You can configure certain caching behaviors for generated query plans and APQ (but not introspection responses). For details, see [In-Memory Caching in the router](/router/configuration/in-memory-caching/). **If you have a GraphOS Enterprise plan:** -- You can configure a Redis-backed _distributed_ cache that enables multiple router instances to share cached values. For details, see [Distributed caching in the GraphOS Router](./distributed-caching/). -- You can configure a Redis-backed _entity_ cache that enables a client query to retrieve cached entity data split between subgraph reponses. For details, see [Subgraph entity caching in the GraphOS Router](./entity-caching/). +- You can configure a Redis-backed _distributed_ cache that enables multiple router instances to share cached values. For details, see [Distributed caching in the GraphOS Router](/router/configuration/distributed-caching/). +- You can configure a Redis-backed _entity_ cache that enables a client query to retrieve cached entity data split between subgraph reponses. For details, see [Subgraph entity caching in the GraphOS Router](/router/configuration/entity-caching/). + + + +### Native query planner + + + +Starting with v1.49.0, the router can run a Rust-native query planner. This native query planner can be run by itself to plan all queries, replacing the legacy JavaScript implementation. + + + +Starting with v1.57.0, to run the most performant and resource-efficient native query planner and to disable the V8 JavaScript runtime in the router, set the following options in your `router.yaml`: + +```yaml title="router.yaml" +experimental_query_planner_mode: new +``` + +You can also improve throughput by reducing the size of queries sent to subgraphs with the following option: + +```yaml title="router.yaml" +supergraph: + generate_query_fragments: true +``` + + + +Learn more in [Native Query Planner](/router/executing-operations/native-query-planner) docs. @@ -822,60 +847,65 @@ To ensure sufficient data to distinguish between genuinely unused values and tho Thanks to extended reference reporting, operation checks can more accurately flag issues for changes to enum values and input object fields. See the comparison table below for differences between standard operation checks based on legacy reference reporting and enhanced checks based on extended reference reporting. - - - - - - - + + + + + + + + + - - - - - + + + + + - - - + + - - - + + + - - - - - + + + + + - - - + + + + +
-Standard Check Behavior
-(Legacy reference reporting) -
-Enhanced Check Behavior
-(Extended reference reporting) -
+
+ Standard Check Behavior
+ (Legacy reference reporting) +
+ Enhanced Check Behavior
+ (Extended reference reporting) +
##### Enum value removal -Removing any enum values is considered a breaking change if any operations use the enum.Removing enum values is only a breaking change if historical operations use the specific enum value(s) that were removed.
+ Removing any enum values is considered a breaking change if any operations use the enum.Removing enum values is only a breaking change if historical operations use the specific enum value(s) that were removed.
##### Default argument changes for input object fields -Changing or removing a default argument is generally considered a breaking change, but changing or removing default values for input object fields isn't. - -Changing or removing default values for input object fields is considered a breaking change. -You can [configure checks to ignore default values changes](/graphos/delivery/schema-checks/#ignored-conditions-settings). + + Changing or removing a default argument is generally considered a breaking change, but changing or removing default values for input object fields isn't. + + Changing or removing default values for input object fields is considered a breaking change. +You can [configure checks to ignore default values changes](/graphos/platform/schema-management/checks#ignored-conditions-settings). -
+
##### Nullable input object field removal -Removing a nullable input object field is always considered a breaking change.Removing a nullable input object field is only considered a breaking change if the nullable field is present in historical operations. If the nullable field is always omitted in historical operations, its removal isn't considered a breaking change.
+ Removing a nullable input object field is always considered a breaking change.Removing a nullable input object field is only considered a breaking change if the nullable field is present in historical operations. If the nullable field is always omitted in historical operations, its removal isn't considered a breaking change.
##### Changing nullable input object fields to non-nullable -Changing a nullable input object field to non-nullable is considered a breaking change.Changing a nullable input object field to non-nullable is only considered a breaking change if the field had a null value in historical operations. If the field was always a non-null value in historical operations, changing it to non-nullable isn't considered a breaking change.
Changing a nullable input object field to non-nullable is considered a breaking change.Changing a nullable input object field to non-nullable is only considered a breaking change if the field had a null value in historical operations. If the field was always a non-null value in historical operations, changing it to non-nullable isn't considered a breaking change.
+ You won't see an immediate change in checks behavior when you first turn on extended reference reporting. @@ -887,59 +917,59 @@ You won't see an immediate change in checks behavior when you first turn on exte You can enhance your graph's security with GraphOS Router 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. -See [Safelisting with persisted queries](./persisted-queries) for more information. +See [Safelisting with persisted queries](/router/configuration/persisted-queries) for more information. ### HTTP header rules -See [Sending HTTP headers to subgraphs](./header-propagation/). +See [Sending HTTP headers to subgraphs](/graphos/routing/header-propagation/). ### Traffic shaping -To configure the shape of traffic between clients, routers, and subgraphs, see [Traffic shaping in the router](./traffic-shaping). +To configure the shape of traffic between clients, routers, and subgraphs, see [Traffic shaping in the router](/router/configuration/traffic-shaping). ### Cross-Origin Resource Sharing (CORS) -See [Configuring CORS in the router](./cors). +See [Configuring CORS in the router](/router/configuration/cors). ### Defer support -See [router support for `@defer`](../executing-operations/defer-support/#disabling-defer). +See [router support for `@defer`](/router/executing-operations/defer-support/#disabling-defer). ### Query batching support -See [GraphOS Router's support for query batching](../executing-operations/query-batching). +See [GraphOS Router's support for query batching](/router/executing-operations/query-batching). ### Subscription support -See [GraphQL subscriptions in the GraphOS Router](../executing-operations/subscription-support/#router-setup). +See [GraphQL subscriptions in the GraphOS Router](/router/executing-operations/subscription-support/#router-setup). ### Authorization support -- To configure authorization directives, see [Authorization directives](./authorization/#authorization-directives). +- To configure authorization directives, see [Authorization directives](/router/configuration/authorization/#authorization-directives). -- To configure the authorization plugin, see [Configuration options](./authorization/#configuration-options). +- To configure the authorization plugin, see [Configuration options](/router/configuration/authorization/#configuration-options). ### JWT authentication -To enable and configure JWT authentication, see [JWT authentication in the GraphOS Router](./authn-jwt). +To enable and configure JWT authentication, see [JWT authentication in the GraphOS Router](/router/configuration/authn-jwt). ### Cross-site request forgery (CSRF) prevention -To configure CSRF prevention, see [CSRF prevention in the router](./csrf). +To configure CSRF prevention, see [CSRF prevention in the router](/router/configuration/csrf). ### Subgraph authentication -To configure subgraph authentication with AWS SigV4, see a [configuration example](./authn-subgraph/#configuration-example). +To configure subgraph authentication with AWS SigV4, see a [configuration example](/router/configuration/authn-subgraph/#configuration-example). ### External coprocessing -See [External coprocessing in the GraphOS Router](../customizations/coprocessor/). +See [External coprocessing in the GraphOS Router](/router/customizations/coprocessor/). ### Telemetry and monitoring The router supports standard and custom instrumentation to collect telemetry data from its request and response processing pipeline to produce logs, metrics and traces to export. -See the [router telemetry overview](./telemetry/overview). +See the [router telemetry overview](/router/configuration/telemetry/overview). ### TLS @@ -1053,7 +1083,22 @@ tls: #### Redis TLS configuration - +For Redis TLS connections, you can set up a client certificate or override the root certificate authority by configuring `tls` in your router's [YAML config file](https://www.apollographql.com/docs/router/overview/#yaml-config-file). For example: + +```yaml +apq: + router: + cache: + redis: + urls: [ "rediss://redis.example.com:6379" ] + #highlight-start + tls: + certificate_authorities: ${file./path/to/ca.crt} + client_authentication: + certificate_chain: ${file./path/to/certificate_chain.pem} + key: ${file./path/to/key.pem} + #highlight-end +``` ### Request limits @@ -1061,7 +1106,7 @@ The GraphOS Router supports enforcing three types of request limits for enhanced - Network-based limits - Lexical, parser-based limits -- Semantic, operation-based limits (this is an [Enterprise feature](../enterprise-features/)) +- Semantic, operation-based limits (this is an [Enterprise feature](/router/enterprise-features/)) The router rejects any request that violates at least one of these limits. @@ -1083,7 +1128,7 @@ limits: #### Operation-based limits (Enterprise only) -See [this article](./operation-limits/). +See [this article](/router/configuration/operation-limits/). #### Network-based limits @@ -1137,7 +1182,7 @@ Note that the router calculates the recursion depth for each operation and fragm ### Demand control -See [Demand Control](../executing-operations/demand-control) to learn how to analyze the cost of operations and to reject requests with operations that exceed customizable cost limits. +See [Demand Control](/router/executing-operations/demand-control) to learn how to analyze the cost of operations and to reject requests with operations that exceed customizable cost limits. ### Early cancel @@ -1159,7 +1204,7 @@ supergraph: ### Plugins -You can customize the router's behavior with [plugins](../customizations/overview). Each plugin can have its own section in the configuration file with arbitrary values: +You can customize the router's behavior with [plugins](/router/customizations/overview). Each plugin can have its own section in the configuration file with arbitrary values: ```yaml {4,8} title="example-plugin-router.yaml" plugins: @@ -1207,6 +1252,12 @@ supergraph: generate_query_fragments: true ``` + + +In the future, the `generate_query_fragments` option will be the only option for handling fragments. + + + ### Reusing configuration You can reuse parts of your configuration file in multiple places using standard YAML aliasing syntax: diff --git a/docs/source/errors.mdx b/docs/source/reference/router/errors.mdx similarity index 86% rename from docs/source/errors.mdx rename to docs/source/reference/router/errors.mdx index 5730dd6fef..f325df83fb 100644 --- a/docs/source/errors.mdx +++ b/docs/source/reference/router/errors.mdx @@ -24,7 +24,6 @@ Requests may receive this response in two cases: -A request used an unallowed HTTP method. @@ -45,7 +44,7 @@ A request's HTTP `Accept` header didn't contain any of the router's supported mi -Request traffic exceeded configured rate limits. See [client side traffic shaping](./configuration/traffic-shaping/#client-side-traffic-shaping). +Request traffic exceeded configured rate limits. See [client side traffic shaping](/router/configuration/traffic-shaping/#client-side-traffic-shaping). @@ -61,14 +60,14 @@ The router encountered an unexpected issue. [Report](https://github.com/apollogr -The request was not able to complete within a configured amount of time. See [client side traffic shaping timeouts](./configuration/traffic-shaping/#timeouts). +The request was not able to complete within a configured amount of time. See [client side traffic shaping timeouts](/router/configuration/traffic-shaping/#timeouts). -You can create Rhai scripts that throw custom status codes. See [Terminating client requests](./customizations/rhai-api#terminating-client-requests) to learn more. +You can create Rhai scripts that throw custom status codes. See [Terminating client requests](/graphos/reference/router/rhai#terminating-client-requests) to learn more. @@ -76,7 +75,7 @@ You can create Rhai scripts that throw custom status codes. See [Terminating cli ### Demand control -Errors returned by the router when [demand control](./executing-operations/demand-control) is enabled. +Errors returned by the router when [demand control](/router/executing-operations/demand-control) is enabled. diff --git a/docs/source/federation-version-support.mdx b/docs/source/reference/router/federation-version-support.mdx similarity index 100% rename from docs/source/federation-version-support.mdx rename to docs/source/reference/router/federation-version-support.mdx diff --git a/docs/source/customizations/rhai-api.mdx b/docs/source/reference/router/rhai.mdx similarity index 97% rename from docs/source/customizations/rhai-api.mdx rename to docs/source/reference/router/rhai.mdx index c21f39f47c..4a74cc28f9 100644 --- a/docs/source/customizations/rhai-api.mdx +++ b/docs/source/reference/router/rhai.mdx @@ -4,11 +4,11 @@ subtitle: APIs for router customizations description: This reference documents the symbols and behaviors that are specific to Rhai customizations for the Apollo GraphOS Router and Apollo Router Core. Includes entry point hooks, logging, and more. --- -This reference documents the symbols and behaviors that are specific to [Rhai customizations](./rhai/) for the GraphOS Router and Apollo Router Core. +This reference documents the symbols and behaviors that are specific to [Rhai customizations](/graphos/routing/customization/rhai/) for the GraphOS Router and Apollo Router Core. ## Entry point hooks -Your Rhai script's [main file](./rhai/#the-main-file) hooks into the individual services of the router's [request-handling lifecycle](./rhai/#router-request-lifecycle). To do so, it defines whichever combination of the following entry point hooks it requires: +Your Rhai script's [main file](/graphos/routing/customization/rhai/#the-main-file) hooks into the individual services of the router's [request-handling lifecycle](/graphos/routing/customization/rhai/#router-request-lifecycle). To do so, it defines whichever combination of the following entry point hooks it requires: ```rhai fn router_service(service) {} @@ -17,7 +17,7 @@ fn execution_service(service) {} fn subgraph_service(service, subgraph) {} ``` -Within each hook, you define custom logic to interact with the current active request and/or response as needed. This most commonly involves using methods of the provided `service` object to [register service callbacks](./rhai/#service-callbacks), like so: +Within each hook, you define custom logic to interact with the current active request and/or response as needed. This most commonly involves using methods of the provided `service` object to [register service callbacks](/graphos/routing/customization/rhai/#service-callbacks), like so: ```rhai title="main.rhai" fn supergraph_service(service) { @@ -117,7 +117,7 @@ fn supergraph_service(service) { } ``` -Rhai throws at the `map_request` layer behave the same as `ControlFlow::Break`, which is explained in the [external extensibility section](./coprocessor/#terminating-a-client-request). +Rhai throws at the `map_request` layer behave the same as `ControlFlow::Break`, which is explained in the [external extensibility section](/router/customizations/coprocessor/#terminating-a-client-request). If the supplied status code is not a valid HTTP status code, then a `500` response code will result. diff --git a/docs/source/quickstart.mdx b/docs/source/reference/router/self-hosted-install.mdx similarity index 97% rename from docs/source/quickstart.mdx rename to docs/source/reference/router/self-hosted-install.mdx index 9e6649d1a7..c6711568ba 100644 --- a/docs/source/quickstart.mdx +++ b/docs/source/reference/router/self-hosted-install.mdx @@ -4,7 +4,7 @@ subtitle: Run the router with GraphOS and Apollo-hosted subgraphs description: This quickstart tutorial walks you through installing the Apollo GraphOS Router or Apollo Router Core and running it with GraphOS and some example Apollo-hosted subgraphs. --- -import ElasticNotice from "../shared/elastic-notice.mdx"; +import ElasticNotice from "../../../shared/elastic-notice.mdx"; Hello! This tutorial walks you through installing the router (GraphOS Router or Apollo Router Core) and running it in with GraphOS and some example Apollo-hosted subgraphs. @@ -259,7 +259,7 @@ That's it! Running the router with the `--dev` flag enables a development mode t **Do not use the `--dev` flag in a non-development environment.** It relaxes certain default configuration options to provide an improved local development experience (e.g., it exposes subgraph error messages to clients). -[Learn more about dev mode defaults.](./configuration/overview#dev-mode-defaults) +[Learn more about dev mode defaults.](/router/configuration/overview#dev-mode-defaults) @@ -270,5 +270,5 @@ Visit `http://127.0.0.1:4000` to open Apollo Sandbox, inspect your entire superg Now that you know how to run the router with a supergraph schema, you can: - Set up [managed federation](/federation/managed-federation/overview) -- Learn about [additional configuration options](./configuration/overview) +- Learn about [additional configuration options](/router/configuration/overview) - [Estimate the system resources needed to deploy the router](/technotes/TN0045-router_resource_estimator/). diff --git a/docs/source/configuration/telemetry/instrumentation/conditions.mdx b/docs/source/reference/router/telemetry/instrumentation/conditions.mdx similarity index 89% rename from docs/source/configuration/telemetry/instrumentation/conditions.mdx rename to docs/source/reference/router/telemetry/instrumentation/conditions.mdx index d67c75572e..e98316df27 100644 --- a/docs/source/configuration/telemetry/instrumentation/conditions.mdx +++ b/docs/source/reference/router/telemetry/instrumentation/conditions.mdx @@ -4,7 +4,7 @@ subtitle: Set conditions for when events or instruments are triggered description: Set conditions for when events or instruments are triggered in the Apollo GraphOS Router. --- -You can set conditions for when an [instrument](./instruments) should be mutated or an [event](./events) should be triggered. +You can set conditions for when an [instrument](/router/configuration/telemetry/instrumentation/instruments) should be mutated or an [event](/router/configuration/telemetry/instrumentation/events) should be triggered. ## Condition configuration @@ -35,7 +35,7 @@ telemetry: #### `exists` -The `exists` condition is testing if [selectors](./selectors) is present. +The `exists` condition is testing if [selectors](/router/configuration/telemetry/instrumentation/selectors) is present. For example, the following condition checks the value of `x-req-header` exists: @@ -46,7 +46,7 @@ exists: #### `eq` -The `eq` condition is an equality test between [selectors](./selectors) or values. +The `eq` condition is an equality test between [selectors](/router/configuration/telemetry/instrumentation/selectors) or values. For example, the following condition checks the value of `x-req-header` is equal to `val`: diff --git a/docs/source/configuration/telemetry/instrumentation/events.mdx b/docs/source/reference/router/telemetry/instrumentation/events.mdx similarity index 86% rename from docs/source/configuration/telemetry/instrumentation/events.mdx rename to docs/source/reference/router/telemetry/instrumentation/events.mdx index a4a3418f44..dd06fd6c26 100644 --- a/docs/source/configuration/telemetry/instrumentation/events.mdx +++ b/docs/source/reference/router/telemetry/instrumentation/events.mdx @@ -4,10 +4,10 @@ subtitle: Capture events from the router's request lifecycle description: Capture standard and custom events from the Apollo GraphOS Router's request lifecycle services. --- -import RouterServices from '../../../../shared/router-lifecycle-services.mdx'; -import TelemetryPerformanceNote from '../../../../shared/telemetry-performance.mdx'; +import RouterServices from '../../../../../shared/router-lifecycle-services.mdx'; +import TelemetryPerformanceNote from '../../../../../shared/telemetry-performance.mdx'; -An _event_ is used to signal when something of note happens in the [GraphOS Router's request lifecycle](../../../customizations/overview/#the-request-lifecycle). Events are output to both logs and traces. +An _event_ is used to signal when something of note happens in the [GraphOS Router's request lifecycle](/router/customizations/overview/#the-request-lifecycle). Events are output to both logs and traces. You can configure events for each service in `router.yaml`. Events can be standard or custom, and they can be triggered by configurable conditions. @@ -60,7 +60,7 @@ telemetry: # ... ``` -But you can also enable these standard events based on [conditions](./conditions) (not supported on batched requests). +But you can also enable these standard events based on [conditions](/router/configuration/telemetry/instrumentation/conditions) (not supported on batched requests). For example: ```yaml title="router.yaml" @@ -174,13 +174,13 @@ telemetry: - response_status: Code ``` -For more details, see [Conditions](./conditions). +For more details, see [Conditions](/router/configuration/telemetry/instrumentation/conditions). ### `attributes` Custom events may have attributes attached to them from the router's request lifecycle. These attributes are used to filter and group spans in your APM. -Attributes may be drawn from [standard attributes](./standard-attributes) or [selectors](./selectors). +Attributes may be drawn from [standard attributes](/router/configuration/telemetry/instrumentation/standard-attributes) or [selectors](/router/configuration/telemetry/instrumentation/selectors). The attributes available depend on the service of the request lifecycle. ```yaml title="future.router.yaml" @@ -236,8 +236,8 @@ telemetry: | Option | Values | Default | Description | |--------------------|------------------------------------------------------------------------------|---------|-------------------------------------------------------------| | `` | | | The name of the custom attribute. | -| `attributes` | [standard attributes](./standard-attributes) or [selectors](./selectors) | | The attributes of the custom log event. | -| `condition` | [conditions](./conditions) | | The condition that must be met for the event to be emitted. | +| `attributes` | [standard attributes](/router/configuration/telemetry/instrumentation/standard-attributes) or [selectors](/router/configuration/telemetry/instrumentation/selectors) | | The attributes of the custom log event. | +| `condition` | [conditions](/router/configuration/telemetry/instrumentation/conditions) | | The condition that must be met for the event to be emitted. | | `error` | `trace`\|`info`\|`warn`\|`error`\| `off` | `off` | The level of the error log event. | | `level` | `trace`\|`info`\|`warn`\|`error`\| `off` | `off` | The level of the custom log event. | | `message` | | | The message of the custom log event. | diff --git a/docs/source/configuration/telemetry/instrumentation/instruments.mdx b/docs/source/reference/router/telemetry/instrumentation/instruments.mdx similarity index 92% rename from docs/source/configuration/telemetry/instrumentation/instruments.mdx rename to docs/source/reference/router/telemetry/instrumentation/instruments.mdx index 1b32ce2409..ecec8d1852 100644 --- a/docs/source/configuration/telemetry/instrumentation/instruments.mdx +++ b/docs/source/reference/router/telemetry/instrumentation/instruments.mdx @@ -4,8 +4,8 @@ subtitle: Collect measurements with standard and custom instruments description: Create and customize instruments to collect data and report measurements from the Apollo GraphOS Router's request lifecycle services. --- -import RouterServices from '../../../../shared/router-lifecycle-services.mdx'; -import TelemetryPerformanceNote from '../../../../shared/telemetry-performance.mdx'; +import RouterServices from '../../../../../shared/router-lifecycle-services.mdx'; +import TelemetryPerformanceNote from '../../../../../shared/telemetry-performance.mdx'; An _instrument_ in the router collects data and reports measurements to a metric backend. Supported instruments include standard instruments from OpenTelemetry, standard instruments for the router's request lifecycle, and custom instruments. Supported instrument kinds are counters and histograms. @@ -68,7 +68,7 @@ telemetry: ### Apollo standard instruments -To learn about Apollo-provided standard metric instruments for the router's request lifecycle, see [router instruments](./standard-instruments). +To learn about Apollo-provided standard metric instruments for the router's request lifecycle, see [router instruments](/router/configuration/telemetry/instrumentation/standard-instruments). ### Custom instruments @@ -314,7 +314,7 @@ The [service](#router-request-lifecycle-services) you define an instrument on de -`event_*` are mandantory when you want to use a [selector](./selectors) on the supergraph response body (`response_data` and `response_errors`). +`event_*` are mandantory when you want to use a [selector](/router/configuration/telemetry/instrumentation/selectors) on the supergraph response body (`response_data` and `response_errors`). @@ -408,7 +408,7 @@ telemetry: Instruments may have attributes attached to them from the router pipeline. These attributes are used to filter and group metrics in your APM. -Attributes may be drawn from [standard attributes](./standard-attributes) or [selectors](./selectors) except for the standard metric `http.server.active_requests`. +Attributes may be drawn from [standard attributes](/router/configuration/telemetry/instrumentation/standard-attributes) or [selectors](/router/configuration/telemetry/instrumentation/selectors) except for the standard metric `http.server.active_requests`. The attributes available depend on the service of the pipeline. @@ -474,8 +474,8 @@ telemetry: |-----------------------------|--------------------------------------------------------------------------------|------------|-----------------------------------------------| | `` | | | The name of the custom attribute. | | `` | | | The name of the custom instrument. | -| `attributes` | [standard attributes](./standard-attributes) or [selectors](./selectors) | | The attributes of the custom instrument. | -| `condition` | [conditions](./conditions) | | The condition for mutating the instrument. | +| `attributes` | [standard attributes](/router/configuration/telemetry/instrumentation/standard-attributes) or [selectors](/router/configuration/telemetry/instrumentation/selectors) | | The attributes of the custom instrument. | +| `condition` | [conditions](/router/configuration/telemetry/instrumentation/conditions) | | The condition for mutating the instrument. | | `default_requirement_level` | `required`\|`recommended` | `required` | The default attribute requirement level. | | `type` | `counter`\|`histogram` | | The name of the custom instrument. | | `unit` | | | A unit name, for example `By` or `{request}`. | diff --git a/docs/source/configuration/telemetry/instrumentation/selectors.mdx b/docs/source/reference/router/telemetry/instrumentation/selectors.mdx similarity index 96% rename from docs/source/configuration/telemetry/instrumentation/selectors.mdx rename to docs/source/reference/router/telemetry/instrumentation/selectors.mdx index 312375f26c..580ed124ca 100644 --- a/docs/source/configuration/telemetry/instrumentation/selectors.mdx +++ b/docs/source/reference/router/telemetry/instrumentation/selectors.mdx @@ -3,9 +3,9 @@ title: Selectors subtitle: Select data from the router pipeline to extract description: Extract and select data from the Apollo GraphOS Router's pipeline services to attach to telemetry. --- -import RouterServices from '../../../../shared/router-lifecycle-services.mdx'; +import RouterServices from '../../../../../shared/router-lifecycle-services.mdx'; -A _selector_ is used to extract data from the GraphOS Router's request lifecycle (pipeline) services and attach them to telemetry. Specifically [spans](./spans), [instruments](./instruments), [conditions](./conditions) and [events](./events). +A _selector_ is used to extract data from the GraphOS Router's request lifecycle (pipeline) services and attach them to telemetry, specifically [spans](/router/configuration/telemetry/instrumentation/spans), [instruments](/router/configuration/telemetry/instrumentation/instruments), [conditions](/router/configuration/telemetry/instrumentation/conditions) and [events](/router/configuration/telemetry/instrumentation/events). An example of a selector, `request_header`, of the router service on a custom span attribute: diff --git a/docs/source/configuration/telemetry/instrumentation/spans.mdx b/docs/source/reference/router/telemetry/instrumentation/spans.mdx similarity index 87% rename from docs/source/configuration/telemetry/instrumentation/spans.mdx rename to docs/source/reference/router/telemetry/instrumentation/spans.mdx index 73dddd58e0..70016ebdb0 100644 --- a/docs/source/configuration/telemetry/instrumentation/spans.mdx +++ b/docs/source/reference/router/telemetry/instrumentation/spans.mdx @@ -4,9 +4,9 @@ subtitle: Add router lifecycle context to traces description: Use spans to add contextual information from the Apollo GraphOS Router or Apollo Router Core to traces displayed by your application performance monitors (APM). --- -import RouterServices from '../../../../shared/router-lifecycle-services.mdx'; +import RouterServices from '../../../../../shared/router-lifecycle-services.mdx'; -A **span** captures contextual information about requests and responses as they're processed through the [router's request lifecycle (pipeline)](../../../customizations/overview/#the-request-lifecycle). The information from spans can be used when displaying traces in your application performance monitors (APM). +A **span** captures contextual information about requests and responses as they're processed through the [router's request lifecycle (pipeline)](/router/customizations/overview/#the-request-lifecycle). The information from spans can be used when displaying traces in your application performance monitors (APM). ## Spans configuration @@ -35,7 +35,7 @@ telemetry: Spans may have attributes attached to them from the router pipeline. These attributes are used to filter and group spans in your APM. -Attributes may be drawn from [standard attributes](./standard-attributes) or [selectors](./selectors). +Attributes may be drawn from [standard attributes](/router/configuration/telemetry/instrumentation/standard-attributes) or [selectors](/router/configuration/telemetry/instrumentation/selectors). @@ -58,7 +58,7 @@ telemetry: response_header: "x-my-header" ``` -You can also have [conditions](./conditions) on custom attributes using [selectors](./selectors). You can only have conditions on a selector at the same execution level. +You can also have [conditions](/router/configuration/telemetry/instrumentation/conditions) on custom attributes using [selectors](/router/configuration/telemetry/instrumentation/selectors). You can only have conditions on a selector at the same execution level. Example you can't have a condition on `response_header` if you want to set an attribute from `request_header`. ```yaml title="desc.router.yaml" @@ -245,8 +245,8 @@ telemetry: | Option | Values | Default | Description | |---------------------------------------|---------------------------------------------------------------------------|--------------------------------|------------------------------------------| | `` | | | The name of the custom attribute. | -| `attributes` | [standard attributes](./standard-attributes)\|[selectors](./selectors) | | The attributes of the span. | -| `condition` | [conditions](./conditions) | | The condition for adding a custom attribute. | +| `attributes` | [standard attributes](/router/configuration/telemetry/instrumentation/standard-attributes)\|[selectors](/router/configuration/telemetry/instrumentation/selectors) | | The attributes of the span. | +| `condition` | [conditions](/router/configuration/telemetry/instrumentation/conditions) | | The condition for adding a custom attribute. | | `default_attribute_requirement_level` | `required`\|`recommended` | `required` | The default attribute requirement level. | | `mode` | `spec_compliant` \| `deprecated` | `deprecated` | The attributes of the span. | diff --git a/docs/source/configuration/telemetry/instrumentation/standard-attributes.mdx b/docs/source/reference/router/telemetry/instrumentation/standard-attributes.mdx similarity index 89% rename from docs/source/configuration/telemetry/instrumentation/standard-attributes.mdx rename to docs/source/reference/router/telemetry/instrumentation/standard-attributes.mdx index 5df84f52bf..b1440ca115 100644 --- a/docs/source/configuration/telemetry/instrumentation/standard-attributes.mdx +++ b/docs/source/reference/router/telemetry/instrumentation/standard-attributes.mdx @@ -4,9 +4,9 @@ subtitle: Attach standard attributes to router telemetry description: Attach OpenTelemetry (OTel) standard attributes to Apollo GraphOS Router or Apollo Router Core telemetry. --- -import RouterServices from '../../../../shared/router-lifecycle-services.mdx'; +import RouterServices from '../../../../../shared/router-lifecycle-services.mdx'; -[OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/semconv/) define a set of **standard attributes** that can be attached to [spans](./spans), [instruments](./instruments) and [events](./events). These attributes are used to filter and group data in your application performance monitor (APM). +[OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/semconv/) define a set of **standard attributes** that can be attached to [spans](/router/configuration/telemetry/instrumentation/spans), [instruments](/router/configuration/telemetry/instrumentation/instruments) and [events](/router/configuration/telemetry/instrumentation/events). These attributes are used to filter and group data in your application performance monitor (APM). The attributes available depend on the service of the router pipeline. @@ -93,9 +93,9 @@ Standard attributes of the `supergraph` service: | Attribute | Values | Description | |-----------------------------|-------------------------------------|---------------------------------------------| -| `graphql.operation.name` | | The operation name from the graphql query (need `spec_compliant` [mode](./spans/#mode) to disable it) | +| `graphql.operation.name` | | The operation name from the graphql query (need `spec_compliant` [mode](/router/configuration/telemetry/instrumentation/spans/#mode) to disable it) | | `graphql.operation.type` | `query`\|`mutation`\|`subscription` | The operation kind from the subgraph query | -| `graphql.document` | | The GraphQL query to the subgraph (need `spec_compliant` [mode](./spans/#mode) to disable it) | +| `graphql.document` | | The GraphQL query to the subgraph (need `spec_compliant` [mode](/router/configuration/telemetry/instrumentation/spans/#mode) to disable it) | #### Subgraph @@ -104,7 +104,7 @@ Standard attributes of the `subgraph` service: | Attribute | Values | Description | |------------------------------------|-------------------------------------|------------------------------------------------| -| `subgraph.name` | | The name of the subgraph (need `spec_compliant` [mode](./spans/#mode) to disable it) | -| `subgraph.graphql.operation.name` | | The operation name from the subgraph query (need `spec_compliant` [mode](./spans/#mode) to disable it) | +| `subgraph.name` | | The name of the subgraph (need `spec_compliant` [mode](/router/configuration/telemetry/instrumentation/spans/#mode) to disable it) | +| `subgraph.graphql.operation.name` | | The operation name from the subgraph query (need `spec_compliant` [mode](/router/configuration/telemetry/instrumentation/spans/#mode) to disable it) | | `subgraph.graphql.operation.type` | `query`\|`mutation`\|`subscription` | The operation kind from the subgraph query | -| `subgraph.graphql.document` | | The GraphQL query to the subgraph (need `spec_compliant` [mode](./spans/#mode) to disable it) | +| `subgraph.graphql.document` | | The GraphQL query to the subgraph (need `spec_compliant` [mode](/router/configuration/telemetry/instrumentation/spans/#mode) to disable it) | diff --git a/docs/source/configuration/telemetry/instrumentation/standard-instruments.mdx b/docs/source/reference/router/telemetry/instrumentation/standard-instruments.mdx similarity index 97% rename from docs/source/configuration/telemetry/instrumentation/standard-instruments.mdx rename to docs/source/reference/router/telemetry/instrumentation/standard-instruments.mdx index 7f10f228c1..bf0101d802 100644 --- a/docs/source/configuration/telemetry/instrumentation/standard-instruments.mdx +++ b/docs/source/reference/router/telemetry/instrumentation/standard-instruments.mdx @@ -8,7 +8,7 @@ description: Reference of standard metric instruments for the request lifecycle GraphOS Router and Apollo Router Core provide a set of non-configurable metric instruments that expose detailed information about the router's request lifecycle. -These instruments can be consumed by configuring a [metrics exporter](../exporters/metrics/overview). +These instruments can be consumed by configuring a [metrics exporter](/router/configuration/telemetry/exporters/metrics/overview). ### HTTP @@ -98,7 +98,7 @@ The initial call to Uplink during router startup is not reflected in metrics. -[Learn more about subscriptions.](../../../executing-operations/subscription-support/) +[Learn more about subscriptions.](/router/executing-operations/subscription-support/) diff --git a/docs/source/configuration/telemetry/exporters/logging/overview.mdx b/docs/source/reference/router/telemetry/log-exporters/overview.mdx similarity index 97% rename from docs/source/configuration/telemetry/exporters/logging/overview.mdx rename to docs/source/reference/router/telemetry/log-exporters/overview.mdx index 3f763ac437..f1cef8cff1 100644 --- a/docs/source/configuration/telemetry/exporters/logging/overview.mdx +++ b/docs/source/reference/router/telemetry/log-exporters/overview.mdx @@ -6,7 +6,7 @@ description: Configure logging in the Apollo GraphOS Router or Apollo Router Cor GraphOS Router and Apollo Router Core provide built-in logging to capture records about their activity. -The router supports [configurable log levels](#log-level) and [stdout output](./stdout) of log messages (with [configurable output formats](./stdout/#logging-output-format)). +The router supports [configurable log levels](#log-level) and [stdout output](/router/configuration/telemetry/exporters/logging/stdout) of log messages (with [configurable output formats](/router/configuration/telemetry/exporters/logging/stdout/#logging-output-format)). ## Log level diff --git a/docs/source/configuration/telemetry/exporters/logging/stdout.mdx b/docs/source/reference/router/telemetry/log-exporters/stdout.mdx similarity index 97% rename from docs/source/configuration/telemetry/exporters/logging/stdout.mdx rename to docs/source/reference/router/telemetry/log-exporters/stdout.mdx index a85e8162a6..fddae9b1be 100644 --- a/docs/source/configuration/telemetry/exporters/logging/stdout.mdx +++ b/docs/source/reference/router/telemetry/log-exporters/stdout.mdx @@ -6,7 +6,7 @@ description: Configure logging output to stdout in the Apollo GraphOS Router or You can configure GraphOS Router or Apollo Router Core logging to be directed to stdout, and its output format can be set to text or JSON. -For general logging configuration, refer to [Router Logging Configuration](./overview). +For general logging configuration, refer to [Router Logging Configuration](/router/configuration/telemetry/exporters/logging/overview). ## stdout configuration @@ -31,7 +31,7 @@ You can configure the logging output format. The default format depends on how t * In an interactive shell, [`text`](#text) is the default. * In a non-interactive shell, [`json`](#json) is the default. -You can explicitly set the format in [`router.yaml`](../../../overview#yaml-config-file) with `telemetry.exporters.logging.stdout.format`: +You can explicitly set the format in [`router.yaml`](/router/configuration/overview#yaml-config-file) with `telemetry.exporters.logging.stdout.format`: ```yaml title="router.yaml" telemetry: @@ -51,7 +51,7 @@ If both `format` and `tty_format` are configured then the output depends on the * In an interactive shell, `tty_format` will take precedence. * In a non-interactive shell, `format` will take precedence. -You can explicitly set the format in [`router.yaml`](../../../overview#yaml-config-file) with `telemetry.exporters.logging.stdout.tty_format`: +You can explicitly set the format in [`router.yaml`](/router/configuration/overview#yaml-config-file) with `telemetry.exporters.logging.stdout.tty_format`: ```yaml title="router.yaml" telemetry: diff --git a/docs/source/configuration/telemetry/exporters/metrics/datadog.mdx b/docs/source/reference/router/telemetry/metrics-exporters/datadog.mdx similarity index 74% rename from docs/source/configuration/telemetry/exporters/metrics/datadog.mdx rename to docs/source/reference/router/telemetry/metrics-exporters/datadog.mdx index 5ec3ed40df..4aa7850a76 100644 --- a/docs/source/configuration/telemetry/exporters/metrics/datadog.mdx +++ b/docs/source/reference/router/telemetry/metrics-exporters/datadog.mdx @@ -4,9 +4,9 @@ subtitle: Configure the Datadog exporter for metrics description: Configure the Datadog exporter for metrics via OpenTelemetry Protocol (OTLP) in the Apollo GraphOS Router or Apollo Router Core. --- -Enable and configure the [OTLP exporter](./otlp) for metrics in the GraphOS Router or Apollo Router Core for use with [Datadog](https://www.datadoghq.com/). +Enable and configure the [OTLP exporter](/router/configuration/telemetry/exporters/metrics/otlp) for metrics in the GraphOS Router or Apollo Router Core for use with [Datadog](https://www.datadoghq.com/). -For general tracing configuration, refer to [Router Metrics Configuration](./overview). +For general tracing configuration, refer to [Router Metrics Configuration](/router/configuration/telemetry/exporters/metrics/overview). ## Datadog configuration @@ -28,7 +28,7 @@ otlp_config: ``` ### Router configuration -To configure the router, enable the [OTLP exporter](./otlp#configuration) and set both `temporality: delta` and `endpoint: `. For example: +To configure the router, enable the [OTLP exporter](/router/configuration/telemetry/exporters/metrics/otlp#configuration) and set both `temporality: delta` and `endpoint: `. For example: ```yaml title="router.yaml" telemetry: diff --git a/docs/source/configuration/telemetry/exporters/metrics/dynatrace.mdx b/docs/source/reference/router/telemetry/metrics-exporters/dynatrace.mdx similarity index 85% rename from docs/source/configuration/telemetry/exporters/metrics/dynatrace.mdx rename to docs/source/reference/router/telemetry/metrics-exporters/dynatrace.mdx index dfd00f1c8d..fedb7f9e90 100644 --- a/docs/source/configuration/telemetry/exporters/metrics/dynatrace.mdx +++ b/docs/source/reference/router/telemetry/metrics-exporters/dynatrace.mdx @@ -4,15 +4,15 @@ subtitle: Configure the Dynatrace exporter for metrics description: Configure the Dynatrace exporter for metrics via OpenTelemetry Protocol (OTLP) in the Apollo Router. --- -Enable and configure the [OTLP exporter](./otlp) for metrics in the Apollo Router for use with [Dynatrace](https://dynatrace.com/). +Enable and configure the [OTLP exporter](/router/configuration/telemetry/exporters/metrics/otlp) for metrics in the Apollo Router for use with [Dynatrace](https://dynatrace.com/). -For general tracing configuration, refer to [Router Metrics Configuration](./overview). +For general tracing configuration, refer to [Router Metrics Configuration](/router/configuration/telemetry/exporters/metrics/overview). ## Dynatrace configuration To configure the router: -- Enable the [OTLP exporter](./otlp#configuration) +- Enable the [OTLP exporter](/router/configuration/telemetry/exporters/metrics/otlp#configuration) - Set `temporality: delta` (Using _Delta_ is required as _Cumulative_ temporality is **not** supported by Dynatrace) - Set the `protocol` as `http` (Dynatrace [doesn't currently support](https://docs.dynatrace.com/docs/extend-dynatrace/opentelemetry/getting-started/otlp-export) gRPC) - Set the `endpoint` to your [Dynatrace OpenTelemetry metrics endpoint](https://docs.dynatrace.com/docs/dynatrace-api/environment-api/opentelemetry/post-metrics) (e.g., ensuring that it contains `{your-environment-id}` in the hostname and ends in `/api/v2/otlp/v1/metrics`) diff --git a/docs/source/configuration/telemetry/exporters/metrics/new-relic.mdx b/docs/source/reference/router/telemetry/metrics-exporters/new-relic.mdx similarity index 71% rename from docs/source/configuration/telemetry/exporters/metrics/new-relic.mdx rename to docs/source/reference/router/telemetry/metrics-exporters/new-relic.mdx index 2d4892fb80..656360e73c 100644 --- a/docs/source/configuration/telemetry/exporters/metrics/new-relic.mdx +++ b/docs/source/reference/router/telemetry/metrics-exporters/new-relic.mdx @@ -4,13 +4,13 @@ subtitle: Configure the New Relic exporter for metrics description: Configure the New Relic exporter for metrics via OpenTelemetry Protocol (OTLP) in the Apollo GraphOS Router or Apollo Router Core. --- -Enable and configure the [OTLP exporter](./otlp) for metrics in the GraphOS Router or Apollo Router Core for use with [New Relic](https://newrelic.com/). +Enable and configure the [OTLP exporter](/router/configuration/telemetry/exporters/metrics/otlp) for metrics in the GraphOS Router or Apollo Router Core for use with [New Relic](https://newrelic.com/). -For general metrics configuration, refer to [Router Metrics Configuration](./overview). +For general tracing configuration, refer to [Router Metrics Configuration](/router/configuration/telemetry/exporters/metrics/overview). ## New Relic configuration -To configure the router, enable the [OTLP exporter](./otlp#configuration) with `temporality: delta` and the appropriate endpoint and New Relic API key. +To configure the router, enable the [OTLP exporter](/router/configuration/telemetry/exporters/metrics/otlp#configuration) with `temporality: delta` and the appropriate endpoint and New Relic API key. diff --git a/docs/source/configuration/telemetry/exporters/metrics/otlp.mdx b/docs/source/reference/router/telemetry/metrics-exporters/otlp.mdx similarity index 92% rename from docs/source/configuration/telemetry/exporters/metrics/otlp.mdx rename to docs/source/reference/router/telemetry/metrics-exporters/otlp.mdx index 8699cfe5b4..08042c405a 100644 --- a/docs/source/configuration/telemetry/exporters/metrics/otlp.mdx +++ b/docs/source/reference/router/telemetry/metrics-exporters/otlp.mdx @@ -8,13 +8,13 @@ import BatchProcessorRef from '../../../../../shared/batch-processor-ref.mdx'; Enable and configure the [OpenTelemetry Protocol (OTLP)](https://www.opentelemetry.io/) exporter for metrics in the GraphOS Router or Apollo Router Core. -For general metrics configuration, refer to [Router Metrics Configuration](./overview). +For general metrics configuration, refer to [Router Metrics Configuration](/router/configuration/telemetry/exporters/metrics/overview). Using the OTLP protocol, you can export metrics to any OTLP compatible receiver, including: * [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) -* [Datadog](https://www.datadoghq.com/) (see [configuration instructions](./datadog)) -* [New Relic](https://www.newrelic.com/) (see [configuration instructions](./new-relic)) +* [Datadog](https://www.datadoghq.com/) (see [configuration instructions](/router/configuration/telemetry/exporters/metrics/datadog)) +* [New Relic](https://www.newrelic.com/) (see [configuration instructions](/router/configuration/telemetry/exporters/metrics/new-relic)) ## OTLP configuration @@ -85,7 +85,7 @@ telemetry: -Use the [variable expansion feature](../../../overview#variable-expansion) for referencing environment variables and file paths in YAML configuration files. Use `env.` and `file.` prefixes, for example `${file.ca.txt}`. +Use the [variable expansion feature](/router/configuration/overview#variable-expansion) for referencing environment variables and file paths in YAML configuration files. Use `env.` and `file.` prefixes, for example `${file.ca.txt}`. diff --git a/docs/source/configuration/telemetry/exporters/metrics/overview.mdx b/docs/source/reference/router/telemetry/metrics-exporters/overview.mdx similarity index 89% rename from docs/source/configuration/telemetry/exporters/metrics/overview.mdx rename to docs/source/reference/router/telemetry/metrics-exporters/overview.mdx index b8a2cb256f..efb22e3ccc 100644 --- a/docs/source/configuration/telemetry/exporters/metrics/overview.mdx +++ b/docs/source/reference/router/telemetry/metrics-exporters/overview.mdx @@ -2,16 +2,18 @@ title: Metrics exporters subtitle: Export router metrics description: Collect and export metrics from the Apollo GraphOS Router or Apollo Router Core for Prometheus, OpenTelemetry Protocol (OTLP), Datadog, and New Relic. +redirectFrom: + - /technotes/TN0015-router-to-apm-via-opentelemetry/ --- The GraphOS Router and Apollo Router Core support collection of metrics with [OpenTelemetry](https://opentelemetry.io/), with exporters for: -* [Prometheus](./prometheus) -* [OpenTelemetry Protocol (OTLP)](./otlp) -* [Datadog via OTLP](./datadog) -* [New Relic via OTLP](./new-relic) +* [Prometheus](/router/configuration/telemetry/exporters/metrics/prometheus) +* [OpenTelemetry Protocol (OTLP)](/router/configuration/telemetry/exporters/metrics/otlp) +* [Datadog via OTLP](/router/configuration/telemetry/exporters/metrics/datadog) +* [New Relic via OTLP](/router/configuration/telemetry/exporters/metrics/new-relic) -In [`router.yaml`](../../../overview/#yaml-config-file), you configure router metrics with the following settings: +In [`router.yaml`](/router/configuration/overview/#yaml-config-file), you configure router metrics with the following settings: - `telemetry.exporters.metrics.common`. Configure values for the router which are common across metrics exporters. - `telemetry.exporters.metrics.prometheus`. Configure the Prometheus exporter. @@ -31,7 +33,7 @@ Common metrics configuration contains global settings for all exporters: Set a service name for your router metrics so you can easily locate them in external metrics dashboards. -The service name can be set by an environment variable or in [`router.yaml`](../../../overview/#yaml-config-file), with the following order of precedence (first to last): +The service name can be set by an environment variable or in [`router.yaml`](/router/configuration/overview/#yaml-config-file), with the following order of precedence (first to last): 1. `OTEL_SERVICE_NAME` environment variable 2. `OTEL_RESOURCE_ATTRIBUTES` environment variable @@ -77,7 +79,7 @@ If the service name isn't explicitly set, it defaults to `unknown_service:router A resource attribute is a set of key-value pairs that provide additional information to an exporter. It's an attribute of an [OpenTelemetry resource](https://opentelemetry.io/docs/specs/otel/resource/sdk/). Application performance monitors (APM) can interpret and display resource information. -In [`router.yaml`](../../../overview/#yaml-config-file), resource attributes are set in `telemetry.metrics.common.resource`. For example: +In [`router.yaml`](/router/configuration/overview/#yaml-config-file), resource attributes are set in `telemetry.metrics.common.resource`. For example: ```yaml title="router.yaml" telemetry: @@ -94,7 +96,7 @@ For OpenTelemetry conventions for resources, see [Resource Semantic Conventions] ### `buckets` -You can customize bucket boundaries for all generated histograms by setting `telemetry.exporters.metrics.common.buckets` in [`router.yaml`](../../../overview/#yaml-config-file). For example: +You can customize bucket boundaries for all generated histograms by setting `telemetry.exporters.metrics.common.buckets` in [`router.yaml`](/router/configuration/overview/#yaml-config-file). For example: ```yaml title="router.yaml" telemetry: @@ -186,7 +188,7 @@ telemetry: -OpenTelemetry includes many [standard attributes](https://opentelemetry.io/docs/specs/semconv/attributes-registry/) that you can use via custom [instruments](../../instrumentation/instruments). +OpenTelemetry includes many [standard attributes](https://opentelemetry.io/docs/specs/semconv/attributes-registry/) that you can use via custom [instruments](/router/configuration/telemetry/instrumentation/instruments). @@ -245,4 +247,4 @@ telemetry: ## Related topics * [Connecting OpenTelemetry traces to Prometheus](/technotes/TN0003-opentelemetry-traces-to-prometheus) -* [Sending router traces and metrics to APM tools using OpenTelemetry](/technotes/TN0015-router-to-apm-via-opentelemetry/) +* [Sending router traces and metrics to APM tools using OpenTelemetry](/graphos/reference/router/telemetry/metrics-exporters/overview) diff --git a/docs/source/configuration/telemetry/exporters/metrics/prometheus.mdx b/docs/source/reference/router/telemetry/metrics-exporters/prometheus.mdx similarity index 94% rename from docs/source/configuration/telemetry/exporters/metrics/prometheus.mdx rename to docs/source/reference/router/telemetry/metrics-exporters/prometheus.mdx index 185276a0b7..3123714d14 100644 --- a/docs/source/configuration/telemetry/exporters/metrics/prometheus.mdx +++ b/docs/source/reference/router/telemetry/metrics-exporters/prometheus.mdx @@ -6,11 +6,11 @@ description: Configure the Prometheus metrics exporter endpoint in the Apollo Gr Enable and configure the [Prometheus](https://www.prometheus.io/) exporter for metrics in the GraphOS Router or Apollo Router Core. -For general metrics configuration, refer to [Router Metrics Configuration](./overview). +For general metrics configuration, refer to [Router Metrics Configuration](/router/configuration/telemetry/exporters/metrics/overview). ## Prometheus configuration -To export metrics to Prometheus, enable the Prometheus endpoint and set its address and path in [`router.yaml`](../../../overview#yaml-config-file): +To export metrics to Prometheus, enable the Prometheus endpoint and set its address and path in [`router.yaml`](/router/configuration/overview#yaml-config-file): ```yaml title="router.yaml" telemetry: diff --git a/docs/source/configuration/telemetry/exporters/tracing/datadog.mdx b/docs/source/reference/router/telemetry/trace-exporters/datadog.mdx similarity index 97% rename from docs/source/configuration/telemetry/exporters/tracing/datadog.mdx rename to docs/source/reference/router/telemetry/trace-exporters/datadog.mdx index 0eea7691d9..e1b105d338 100644 --- a/docs/source/configuration/telemetry/exporters/tracing/datadog.mdx +++ b/docs/source/reference/router/telemetry/trace-exporters/datadog.mdx @@ -8,7 +8,7 @@ import BatchProcessorRef from '../../../../../shared/batch-processor-ref.mdx'; Enable and configure the [Datadog](https://www.datadoghq.com/) exporter for tracing in the GraphOS Router or Apollo Router Core. -For general tracing configuration, refer to [Router Tracing Configuration](./overview). +For general tracing configuration, refer to [Router Tracing Configuration](/router/configuration/telemetry/exporters/tracing/overview). ## OTLP configuration @@ -26,7 +26,7 @@ otlp_config: endpoint: :4317 ``` -To configure the router, enable the [OTLP exporter](./otlp) and set `endpoint: `. For example: +To configure the router, enable the [OTLP exporter](/router/configuration/telemetry/exporters/tracing/otlp) and set `endpoint: `. For example: ```yaml title="router.yaml" telemetry: diff --git a/docs/source/configuration/telemetry/exporters/tracing/dynatrace.mdx b/docs/source/reference/router/telemetry/trace-exporters/dynatrace.mdx similarity index 81% rename from docs/source/configuration/telemetry/exporters/tracing/dynatrace.mdx rename to docs/source/reference/router/telemetry/trace-exporters/dynatrace.mdx index 2ba82a6358..db736561d4 100644 --- a/docs/source/configuration/telemetry/exporters/tracing/dynatrace.mdx +++ b/docs/source/reference/router/telemetry/trace-exporters/dynatrace.mdx @@ -4,15 +4,15 @@ subtitle: Configure the Dynatrace exporter for tracing description: Configure the Dynatrace exporter for tracing via OpenTelemetry Protocol (OTLP) in the Apollo Router. --- -Enable and configure the [OTLP exporter](./otlp) for tracing in the Apollo Router for use with [Dynatrace](https://dynatrace.com/). +Enable and configure the [OTLP exporter](/router/configuration/telemetry/exporters/tracing/otlp) for tracing in the Apollo Router for use with [Dynatrace](https://dynatrace.com/). -For general tracing configuration, refer to [Router Tracing Configuration](./overview). +For general tracing configuration, refer to [Router Tracing Configuration](/router/configuration/telemetry/exporters/tracing/overview). ## Dynatrace configuration To configure the router: -- Enable the [OTLP exporter](./otlp#configuration) +- Enable the [OTLP exporter](/router/configuration/telemetry/exporters/tracing/otlp#configuration) - Set the `protocol` as `http`; Dynatrace [doesn't currently support](https://docs.dynatrace.com/docs/extend-dynatrace/opentelemetry/getting-started/otlp-export) `grpc` - Provide your Dynatrace endpoint - Provide your Dynatrace API token in the `Authorization` header; the header should start with [`Api-token` and then your Dynatrace token](https://docs.dynatrace.com/docs/extend-dynatrace/opentelemetry/getting-started/otlp-export#authentication-export-to-activegate) diff --git a/docs/source/configuration/telemetry/exporters/tracing/jaeger.mdx b/docs/source/reference/router/telemetry/trace-exporters/jaeger.mdx similarity index 95% rename from docs/source/configuration/telemetry/exporters/tracing/jaeger.mdx rename to docs/source/reference/router/telemetry/trace-exporters/jaeger.mdx index 7c29456231..28199ec84d 100644 --- a/docs/source/configuration/telemetry/exporters/tracing/jaeger.mdx +++ b/docs/source/reference/router/telemetry/trace-exporters/jaeger.mdx @@ -9,7 +9,7 @@ import BatchProcessorRef from '../../../../../shared/batch-processor-ref.mdx'; Enable and configure the [Jaeger exporter](https://www.jaegertracing.io/) for tracing in the GraphOS Router or Apollo Router Core. -For general tracing configuration, refer to [Router Tracing Configuration](./overview). +For general tracing configuration, refer to [Router Tracing Configuration](/router/configuration/telemetry/exporters/tracing/overview). ## Jaeger OTLP configuration @@ -38,7 +38,7 @@ telemetry: endpoint: "http://${env.JAEGER_HOST}:4317" ``` -See [OTLP configuration](./otlp#configuration) for more details on settings. +See [OTLP configuration](/router/configuration/telemetry/exporters/tracing/otlp#configuration) for more details on settings. ## Jaeger Native configuration diff --git a/docs/source/configuration/telemetry/exporters/tracing/new-relic.mdx b/docs/source/reference/router/telemetry/trace-exporters/new-relic.mdx similarity index 64% rename from docs/source/configuration/telemetry/exporters/tracing/new-relic.mdx rename to docs/source/reference/router/telemetry/trace-exporters/new-relic.mdx index 532816c1df..6afde09486 100644 --- a/docs/source/configuration/telemetry/exporters/tracing/new-relic.mdx +++ b/docs/source/reference/router/telemetry/trace-exporters/new-relic.mdx @@ -4,13 +4,13 @@ subtitle: Configure the New Relic exporter for tracing description: Configure the New Relic exporter for tracing via OpenTelemetry Protocol (OTLP) in the Apollo GraphOS Router or Apollo Router Core. --- -Enable and configure the [OTLP exporter](./otlp) for tracing in the GraphOS Router or Apollo Router Core for use with [New Relic](https://newrelic.com/). +Enable and configure the [OTLP exporter](/router/configuration/telemetry/exporters/tracing/otlp) for tracing in the GraphOS Router or Apollo Router Core for use with [New Relic](https://newrelic.com/). -For general tracing configuration, refer to [Router Tracing Configuration](./overview). +For general tracing configuration, refer to [Router Tracing Configuration](/router/configuration/telemetry/exporters/tracing/overview). ## New Relic configuration -To configure the router, enable the [OTLP exporter](./otlp/#otlp-configuration) and set both `endpoint: ` and `api-key: `. For example: +To configure the router, enable the [OTLP exporter](/router/configuration/telemetry/exporters/tracing/otlp/#otlp-configuration) and set both `endpoint: ` and `api-key: `. For example: ```yaml title="router.yaml" telemetry: diff --git a/docs/source/configuration/telemetry/exporters/tracing/otlp.mdx b/docs/source/reference/router/telemetry/trace-exporters/otlp.mdx similarity index 90% rename from docs/source/configuration/telemetry/exporters/tracing/otlp.mdx rename to docs/source/reference/router/telemetry/trace-exporters/otlp.mdx index dca5ea60c5..fa7ff3a39e 100644 --- a/docs/source/configuration/telemetry/exporters/tracing/otlp.mdx +++ b/docs/source/reference/router/telemetry/trace-exporters/otlp.mdx @@ -11,11 +11,11 @@ Enable and configure the [OpenTelemetry Protocol (OTLP)](https://github.com/open OTLP is the native protocol for OpenTelemetry. It can be used to export traces over HTTP or gRPC to a variety of backends including: * [OpenTelemetry Collector](https://opentelemetry.io/docs/collector/) -* [Datadog](./datadog) -* [Jaeger](./jaeger) -* [New Relic](./new-relic) +* [Datadog](/router/configuration/telemetry/exporters/tracing/datadog) +* [Jaeger](/router/configuration/telemetry/exporters/tracing/jaeger) +* [New Relic](/router/configuration/telemetry/exporters/tracing/new-relic) -For general tracing configuration, refer to [Router Tracing Configuration](./overview). +For general tracing configuration, refer to [Router Tracing Configuration](/router/configuration/telemetry/exporters/tracing/overview). ## OTLP configuration @@ -81,7 +81,7 @@ telemetry: -Use the [variable expansion feature](../../overview#variable-expansion) for referencing environment variables and file paths in YAML configuration files. Use `env.` and `file.` prefixes, for example `${file.ca.txt}`. +Use the [variable expansion feature](/router/configuration/overview#variable-expansion) for referencing environment variables and file paths in YAML configuration files. Use `env.` and `file.` prefixes, for example `${file.ca.txt}`. diff --git a/docs/source/configuration/telemetry/exporters/tracing/overview.mdx b/docs/source/reference/router/telemetry/trace-exporters/overview.mdx similarity index 90% rename from docs/source/configuration/telemetry/exporters/tracing/overview.mdx rename to docs/source/reference/router/telemetry/trace-exporters/overview.mdx index c7b81cca70..ecbabb800d 100644 --- a/docs/source/configuration/telemetry/exporters/tracing/overview.mdx +++ b/docs/source/reference/router/telemetry/trace-exporters/overview.mdx @@ -6,13 +6,13 @@ description: Collect and export tracing information from the Apollo GraphOS Rout The GraphOS Router and Apollo Router Core support collection of traces with [OpenTelemetry](https://opentelemetry.io/), with exporters for: -* [Jaeger](./jaeger) -* [Zipkin](./zipkin) -* [Datadog](./datadog) -* [New Relic](./new-relic) -* [OpenTelemetry Protocol (OTLP)](./otlp) over HTTP or gRPC +* [Jaeger](/router/configuration/telemetry/exporters/tracing/jaeger) +* [Zipkin](/router/configuration/telemetry/exporters/tracing/zipkin) +* [Datadog](/router/configuration/telemetry/exporters/tracing/datadog) +* [New Relic](/router/configuration/telemetry/exporters/tracing/new-relic) +* [OpenTelemetry Protocol (OTLP)](/router/configuration/telemetry/exporters/tracing/otlp) over HTTP or gRPC -The router generates [**spans**](../../instrumentation/spans) that include the various phases of serving a request and associated dependencies. This is useful for showing how response time is affected by: +The router generates [**spans**](/router/configuration/telemetry/instrumentation/spans) that include the various phases of serving a request and associated dependencies. This is useful for showing how response time is affected by: * Sub-request response times * Query shape (sub-request dependencies) @@ -34,7 +34,7 @@ Common tracing configuration contains global settings for all exporters. Set a service name for your router traces so you can easily locate them in external metrics dashboards. -The service name can be set by an environment variable or in [`router.yaml`](../../../overview#yaml-config-file), with the following order of precedence (first to last): +The service name can be set by an environment variable or in [`router.yaml`](/router/configuration/overview#yaml-config-file), with the following order of precedence (first to last): 1. `OTEL_SERVICE_NAME` environment variable 2. `OTEL_RESOURCE_ATTRIBUTES` environment variable @@ -80,7 +80,7 @@ If the service name isn't explicitly set, it defaults to `unknown_service:router A resource attribute is a set of key-value pairs that provide additional information to an exporter. Application performance monitors (APM) may interpret and display resource information. -In [`router.yaml`](../../../overview#yaml-config-file), resource attributes are set in `telemetry.exporters.tracing.common.resource`. For example: +In [`router.yaml`](/router/configuration/overview#yaml-config-file), resource attributes are set in `telemetry.exporters.tracing.common.resource`. For example: ```yaml title="router.yaml" telemetry: @@ -96,7 +96,7 @@ For OpenTelemetry conventions for resources, see [Resource Semantic Conventions] ### `sampler` -You can configure the sampling rate of traces to match the rate of your application performance monitors (APM). To enable sampling configuration, in [`router.yaml`](../../../overview#yaml-config-file) set `telemetry.exporters.tracing.common.sampler` and `telemetry.exporters.tracing.common.parent_based_sampler`: +You can configure the sampling rate of traces to match the rate of your application performance monitors (APM). To enable sampling configuration, in [`router.yaml`](/router/configuration/overview#yaml-config-file) set `telemetry.exporters.tracing.common.sampler` and `telemetry.exporters.tracing.common.parent_based_sampler`: ```yaml title="router.yaml" telemetry: @@ -250,4 +250,4 @@ Using this configuration you will have a response header called `my-trace-id` co ## Related topics * [Connecting OpenTelemetry traces to Prometheus](/technotes/TN0003-opentelemetry-traces-to-prometheus) -* [Sending router traces and metrics to APM tools using OpenTelemetry](/technotes/TN0015-router-to-apm-via-opentelemetry/) +* [Sending router traces and metrics to APM tools using OpenTelemetry](/graphos/reference/router/telemetry/metrics-exporters/overview) diff --git a/docs/source/configuration/telemetry/exporters/tracing/zipkin.mdx b/docs/source/reference/router/telemetry/trace-exporters/zipkin.mdx similarity index 96% rename from docs/source/configuration/telemetry/exporters/tracing/zipkin.mdx rename to docs/source/reference/router/telemetry/trace-exporters/zipkin.mdx index 7b286af618..b4a732999e 100644 --- a/docs/source/configuration/telemetry/exporters/tracing/zipkin.mdx +++ b/docs/source/reference/router/telemetry/trace-exporters/zipkin.mdx @@ -8,7 +8,7 @@ import BatchProcessorRef from '../../../../../shared/batch-processor-ref.mdx'; Enable and configure the [Zipkin](https://zipkin.io/) exporter for tracing in the GraphOS Router or Apollo Router Core. -For general tracing configuration, refer to [Router Tracing Configuration](./overview). +For general tracing configuration, refer to [Router Tracing Configuration](/router/configuration/telemetry/exporters/tracing/overview). ## Zipkin configuration diff --git a/docs/source/routing/about-router.mdx b/docs/source/routing/about-router.mdx new file mode 100644 index 0000000000..55a962573e --- /dev/null +++ b/docs/source/routing/about-router.mdx @@ -0,0 +1,150 @@ +--- +title: Supergraph Routing with GraphOS Router +subtitle: Learn the basics about router features and deployment types +description: Apollo provides cloud and self-hosted GraphOS Router options. The router acts as an entry point to your GraphQL APIs and provides a unified interface for clients to interact with. +redirectFrom: + - /graphos/routing + - /federation/query-plans +--- + +## What is GraphOS Router? + +GraphOS Router is the runtime of the GraphOS platform. It executes client operations by planning and executing subgraph queries, then merging them into client responses. It's also the single entry point and gateway to your federated GraphQL API. + + + + +### Runtime of GraphOS platform + +As the runtime of the [GraphOS platform](/graphos/get-started/concepts/graphos), a GraphOS Router gets the supergraph schema—the blueprint of the federated graphs—from the GraphOS control plane. It then executes incoming clients operations based on that schema. + +Unlike API gateways that offer capabilities to manage API endpoints, the router isn't based on URLs or REST endpoints. Rather, the router is a GraphQL-native solution for handling client APIs. + +### Subgraph query planner + +Whenever your router receives an incoming GraphQL operation, it needs to figure out how to use your subgraphs to populate data for each of that operation's fields. To do this, the router generates a _query plan_: + + + + +A query plan is a blueprint for dividing a single incoming operation into one or more operations that are each resolvable by a single subgraph. Some of these operations depend on the results of other operations, so the query plan also defines any required ordering for their execution. The router's query planner determines the optimal set of subgraph queries for each client operation, then it merges the subgraph responses into a single response for the client. + + + +Use the [Explorer IDE](/graphos/platform/explorer/) to view dynamically calculated example query plans for your operations in its right-hand panel. + + + +### Entry point to federated GraphQL API + +The GraphOS Router is the gateway and entry point to a federated supergraph. Clients send GraphQL operations to your router's public endpoint instead of directly to your APIs. + +## GraphOS Router deployment types + +As the entry point to your supergraph, a GraphOS Router must be able to process the expected load of client operations. The scalability and performance of a router, or a fleet or router instances, can be influenced by their deployment infrastructure. + +### Cloud-hosted routers + +You can choose for Apollo to provision and manage the runtime infrastructure for your routers. Apollo hosts and deploys each instance of router in the cloud. Each _cloud-hosted router_ instance is fully integrated and configurable within GraphOS. + + + + + + +While cloud routers are hosted in the cloud, GraphQL subgraph servers are still hosted in your infrastructure. + + + +### Self-hosted routers + +You can choose to manage the runtime infrastructure for your routers by yourself. Using container images of router, you can host and deploy your router instances from your own infrastructure. These _self-hosted router_ instances allow you full control over their deployment. + + + + +### Common router core + +Both cloud-hosted and self-hosted routers are powered by the [Apollo Router Core](https://github.com/apollographql/router)—a high-performance router packaged as a standalone binary. + +### Router type comparison + +Apollo offers the following router options, in increasing order of configurability: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Router typeDescriptionConfigurabilityPlan availability
Shared cloud routerApollo provisions and manages routers on shared infrastructure. + Basic configurability, including HTTP header rules, CORS settings, and + subgraph error inclusion + + Serverless** +
Dedicated cloud router + Apollo provisions and manages routers on dedicated infrastructure that + you control and scale. + + Highly configurable, including all options for shared cloud routers and + additional configurations + + Dedicated** +
Self-hosted routerYou host and manage the router on your own infrastructure. + Highly configurable and customizable, including all options for Cloud + Dedicated routers and additional [customization options](/graphos/routing/customization/overview). + + The Apollo Router Core is available as a free and source-available router. + Connecting your self-hosted router to GraphOS requires an{' '} + Enterprise plan. +
+ + + +**We've paused new sign-ups for Serverless and Dedicated plans while we improve our offerings based on user feedback. This means cloud routing is temporarily unavailable to new users. In the meantime, you can explore other GraphOS features with a [free trial](https://studio.apollographql.com/signup?referrer=docs-content). + + + +## GraphOS Router features + +Although powered by the source-available Apollo Router Core binary, GraphOS Routers offer an expanded feature set that isn't available when running the Apollo Router Core without connecting it to GraphOS. + +Cloud-hosted routers automatically have access to additional GraphOS Router features, while self-hosted routers must be authenticated with a GraphOS Enterprise license to gain access to these features. Refer to the [pricing page](https://www.apollographql.com/pricing#graphos-router) to compare GraphOS Router features across plan types. + + +## Next steps + +- Learn more about Apollo-managed routers in [cloud-hosted router](/graphos/routing/cloud/) + +- Learn more about deploying router instances in your own infrastructure in [self-hosted router](/graphos/routing/self-hosted/) + +- Learn the basics about configuring a router in [Configuring a Router](/graphos/routing/configure-your-router) + +- For all available configuration options, go to [Router configuration](/graphos/reference/router/configuration) reference docs + +- To learn more about the intricacies of query plans, see the [example graph](/graphos/reference/federation/query-plans#example-graph) and [query plan](/graphos/reference/federation/query-plans#example-graph) in reference docs + +- For the most performant query planning, configure and use the [Rust-native query planner](/graphos/routing/query-planning/native-query-planner). diff --git a/docs/source/routing/cloud/aws-migration.mdx b/docs/source/routing/cloud/aws-migration.mdx new file mode 100644 index 0000000000..a4e9eadcc3 --- /dev/null +++ b/docs/source/routing/cloud/aws-migration.mdx @@ -0,0 +1,159 @@ +--- +title: Migrate Serverless routers to AWS +subtitle: Learn how to migrate Serverless cloud routers from Fly.io to AWS +description: Migrate your Apollo GraphOS Serverless cloud router to AWS for improved reliability and performance. Learn about changes, migration steps, and who needs to migrate. +noIndex: true +--- + + + +This page only applies to Serverless cloud routers created before May 21, 2024. +All Serverless cloud routers created on or after this date automatically run on AWS. + + + +Serverless is switching cloud providers from Fly.io to AWS to improve reliability and performance. +Serverless cloud routers running on Fly.io infrastructure must be migrated in GraphOS Studio. + +## Who needs to migrate? + +You may need to migrate if: + +- Your organization is on a Serverless plan OR +- Your organization is on a Dedicated plan but uses Serverless variants for non-production environments + +To check if you need to migrate, go to [GraphOS Studio](https://studio.apollographql.com?referrer=docs-content). +If a graph's **Cloud Router Details** on the **Overview** page shows **ord - US (Chicago)** as the **Region**, you need to migrate it. + +Cloud router region showing ord - US (Chicago) in GraphOS Studio + +Cloud routers on Fly.io will continue to operate until June 27, 2024. After this date, any cloud routers on Fly.io will be permanently deleted and graphs using them will no longer respond to requests. +Don't hesitate to contact [cloud@apollographql.com](mailto:cloud@apollographql.com) with any migration questions or concerns. + +## What's changing? + +The move to AWS improves reliability and performance. It also changes the cloud hosting region and inactivity periods. +With improved reliability and performance, Serverless can offer additional GraphOS Router features. Refer to the [pricing page](https://www.apollographql.com/pricing#graphos-router) for the full list of supported features. + +### Reliable throughput + +On AWS, Serverless cloud routers can process a consistent 10 requests per second (RPS) of throughput. + + + +If you need more than 10 RPS throughput or have [complex schemas](/graphos/routing/cloud/serverless/#serverless-compute-limitations), consider upgrading to Dedicated. + + + +### Hosting region + +On Fly.io, cloud routers were hosted in Chicago (ord). On AWS, they're hosted in Northern Virginia (us-east-1). This means faster performance, particularly for customers running subgraph servers on AWS, especially if they are in or near us-east-1. + + + +Dedicated offers a [wider variety of AWS regions](/graphos/routing/cloud/dedicated#runs-on-aws). + + + +### Inactivity periods + +On Fly.io, Serverless cloud routers sleep after two minutes of inactivity. Sleeping routers can't serve requests and must wake up to do so. On AWS, cloud routers sleep after seven days of inactivity. + +After a total 30 days of inactivity, Apollo deletes Serverless cloud routers. +Deletion preserves a cloud router's associated variant's schema but deletes the underlying cloud router. Learn more in [Serverless router status](/graphos/routing/cloud/serverless/#serverless-router-status). + +| | Fly.io Hosted | AWS Hosted | +| -------------------------------------- | ------------- | ---------- | +| Inactivity period
before sleep | 2 minutes | 7 days | +| Inactivity period
before deletion | 30 days | 30 days | + +## How to migrate + +Apollo is unable to offer an in-place migration. To migrate, you need to create a new variant on your graph, or create a new graph entirely. Once you create this new variant or graph, you receive a new graph ref and endpoint URL that you must redirect your client traffic to. + + + +To avoid downtime for clients querying your graph, don't delete the variant that houses your existing cloud router until you've created a new one. + + + +### Step 1. Create a new graph + +To get started, create a new graph or variant in GraphOS Studio. See the [getting started](/graphos/quickstart/cloud/#from-an-existing-account) for details on creating a new graph. + + + +**For Dedicated customers with Serverless variants**: + +You can't migrate Serverless variants on a Dedicated plan from Studio. Instead, you must publish a new variant or graph using the [Rover CLI](/rover/commands/subgraphs#publishing-a-subgraph-schema-to-graphos). +All variants created via Rover default to Serverless, even if your organization is on the Dedicated plan. + + + +All Serverless cloud routers created on or after May 21, 2024 automatically run on AWS. +You can confirm your new router is running on AWS by checking that the router region is **AWS us-east-1** on the variant's **Overview** page under **Cloud Router Details**. + +Variant overview page in GraphOS Studio + +Creating a new graph or variant generates a new endpoint URL and graph ref. You'll update these values in later steps. + +### Step 2. Add subgraphs + +Each variant needs at least one subgraph. If you have multiple subgraphs, [add each subgraph](/graphos/quickstart/next-steps/#add-another-subgraph) to your new variant. + +### Step 3. Setup router configuration + +Copy and paste your old router's configuration into your new one. You can access a cloud router's configuration in GraphOS Studio under **Cloud Router > Configuration**. + +Configuring the cloud router in GraphOS Studio + +Router configuration defines important values like CORS policies and header propagation. + + + +If you have [secrets](/graphos/routing/cloud/configuration#managing-secrets) in your old cloud router config, you must also set them in your new one. Secrets can't be read once saved. + + + +### Step 4. Test + +After you've added all your subgraphs and set up your cloud router config, try running a few sample operations from [Explorer](/graphos/platform/explorer/). +You may need to enable [subgraph errors](/graphos/routing/observability/subgraph-error-inclusion) to troubleshoot if your operations don't execute. + +Simulate production traffic before going live. Serverless on AWS offers less but more reliable throughput than on Fly.io. If you exceed throughput limits, your clients receive 429 errors. + + + +It isn't possible to increase throughput on Serverless. If you need more than 10 RPS throughput, consider upgrading to Dedicated. + + + +### Step 5. Go live + +To go live, update the endpoint URL your clients use to query your graph. You can see your new router's endpoint from the **Overview** page of your variant. + +Variant overview page in GraphOS Studio + +If you use any Rover commands in your CI/CD, update the graph ref. + +Once you've updated your client codebase and Rover commands, you can delete the variant housing your Fly.io cloud router. diff --git a/docs/source/routing/cloud/configuration.mdx b/docs/source/routing/cloud/configuration.mdx new file mode 100644 index 0000000000..010ff55b34 --- /dev/null +++ b/docs/source/routing/cloud/configuration.mdx @@ -0,0 +1,373 @@ +--- +title: Cloud Router Configuration +subtitle: Learn how to configure cloud routers in GraphOS Studio +description: Learn about cloud router configurations including HTTP header rules, CORSs settings, secret management, and more in GraphOS Studio. +redirectFrom: + - /graphos/cloud-routing/configuration +--- + +After you create a cloud supergraph, you can manage its router configuration from the **Cloud Router** page in [GraphOS Studio](https://studio.apollographql.com?referrer=docs-content). + +The **General** tab shows the following information: + +- The URL of your router's GraphQL endpoint + - Every cloud router's URL is on a subdomain of `apollographos.net`. +- Your router's current status and [launch history](/graphos/platform/schema-management/delivery/launch) + +From the **Configuration** tab, you can manage the following: + +- [Secrets](#managing-secrets) +- Your router's [YAML-based configuration](#router-configuration-yaml) + +The Cloud Router page in GraphOS Studio + +## Managing secrets + +You can store secret string values that you can then use in your router's [YAML configuration](#router-configuration-yaml). For example, you might store an authorization token that the router needs to include in each of its request to a subgraph. + +To add a new secret, click **Save a secret**. + +In the dialog that appears, enter a name and value for your secret. You can't view a secret's value after you save it, so make sure that the value is correct before saving. When you're ready, click **Save secret**. + +Your secret is encrypted and stored. You can then use the secret's value in your router's YAML configuration. + +The following example YAML configuration uses the value of a secret named `MY_SECRET`: + +```yaml +headers: + all: + request: + - insert: + name: 'subgraph-token' + value: '${env.MY_SECRET}' # highlight-line +``` + +## Router configuration YAML + +You can configure your router's behavior in **Router configuration YAML** on the **Cloud Router** tab or page. + +On the [Serverless plan](https://www.apollographql.com/pricing/), you can configure: + +- [HTTP headers](#http-header-rules) that the router sends to your subgraphs +- [CORS rules](#cors-settings) for browser-based applications connecting to the router +- [Subgraph error inclusion](#subgraph-error-inclusion) to expose subgraph errors to querying clients (including the Apollo Explorer) + +* [Introspection](#introspection) to allow resolving introspection queries. + +[Dedicated and Enterprise plans](https://www.apollographql.com/pricing/) offer a [wider variety of configurations](/graphos/routing/configure-your-router#yaml-file-based-configuration). + +If you require more advanced router customization, get in touch to learn about your about Dedicated and Enterprise plan options. + +### HTTP header rules + +You can configure which HTTP headers your router includes in its requests to each of your subgraphs. You can define per-subgraph header rules, along with rules that apply to all subgraphs. + +You define header rules in your **Router configuration YAML**, like so: + +```yaml +# ...other configuration... +headers: + all: # Header rules for all subgraphs + request: + - propagate: + matching: ^upstream-header-.* + - remove: + named: 'x-legacy-account-id' + subgraphs: + products: # Header rules for just the products subgraph + request: + - insert: + name: 'router-subgraph-name' + value: 'products' +``` + +#### Supported header rules + +Cloud routing supports the following types of header rules: + +##### `propagate` + +Enables you to selectively pass along headers that were included in the client's request to the router. + +You can specify which headers to propagate based on a matching [regular expression pattern](https://docs.rs/regex/latest/regex/): + +```yaml +- propagate: + matching: .* +``` + + + +The router never propagates so-called [hop-by-hop headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#hop-by-hop_headers), such as `Content-Length`, when propagating by pattern. + + + +Alternatively, you can provide a static string via the `named` option. These `named` configurations have additional flexibility, because they support the following options: + +- `default`: A value to set if no value was sent by the client +- `rename`: Renames the header's key to the provided value + +```yaml +- propagate: + named: 'x-user-id' + default: 'abc123' + rename: 'account-id' +``` + +##### `remove` + +Enables you to selectively remove headers that were included in the client's request to the router. Like [`propagate`](#propagate), this option can match either a static string or a [regular expression](https://docs.rs/regex/latest/regex/). + +```yaml +# Do not send this subgraph the "Cookie" header. +- remove: + named: 'Cookie' +- remove: + # Remove headers that include the legacy 'x-' prefix. + matching: ^x-.*$ +``` + +##### `insert` + +Enables you to add custom headers to requests going to a specific subgraph. These headers are always static strings that originate in the router, instead of originating in the client. + +```yaml +- insert: + name: 'sent-from-our-apollo-router' + value: 'indeed' +``` + +#### Rule ordering + +Header rules are applied in the same order they're declared, and later rules can override the effects of earlier rules. Consider this example: + +

+ +```yaml title="bad_configuration.yaml" +headers: + all: + request: + - remove: + named: 'test' + - propagate: + matching: .* +``` + +In this example, first any header named `test` is removed from the list of headers to propagate. However, the list of headers to propagate is currently empty! Next, the `propagate` rule adds all headers to the propagation list, including `test`. + +To correctly remove a header from the propagation list, make sure to define your `remove` rule after any `propagate` rules: + +

+ +```yaml title="good_configuration.yaml" +headers: + all: + request: + - propagate: + matching: .* + - remove: + named: 'test' +``` + +With this ordering, first all headers are added to the propagation list, then the `test` header is removed. + +#### Example + +Here's a complete example that demonstrates all supported `headers` configuration options: + +```yaml +headers: + # Header rules for all subgraphs + all: + request: + # Propagate matching headers + - propagate: + matching: ^upstream-header-.* + # Propagate matching headers + - propagate: + named: 'some-header' + default: 'default-value' + rename: 'destination-header' + # Remove the "x-legacy-account-id" header + - remove: + named: 'x-legacy-account-id' + # Remove matching headers + - remove: + matching: ^x-deprecated-.* + # Insert the 'my-company' header + - insert: + name: 'my-company' + value: 'acme' + # Subgraph-specific header rules + subgraphs: + products: + request: + # Calls to the products subgraph have the "router-subgraph-name" header set to `products`. + - insert: + name: 'router-subgraph-name' + value: 'products' + accounts: + request: + # Calls to the accounts subgraph have the "router-subgraph-name" header set to `accounts`. + - insert: + name: 'router-subgraph-name' + value: 'accounts' +``` + +### CORS settings + + + +If your router serves exclusively non-browser-based clients, you probably don't need to modify the default CORS configuration. + +For a more general introduction to CORS and common considerations, see the following sections: + +- [Why use CORS?](/apollo-server/security/cors#why-use-cors) +- [Choosing CORS options for your project](/apollo-server/security/cors#choosing-cors-options-for-your-project) + + + +By default, the router enables only GraphOS Studio to initiate browser connections to it. If your supergraph serves data to other browser-based applications, you need to do one of the following in the `cors` section of your **Router configuration YAML**: + +- Add the origins of those web applications to the router's list of allowed `origins`. + - Use this option if there is a known, finite list of web applications that consume your cloud supergraph. +- Add a regular expression that matches the origins of those web applications to the router's list of allowed `origins`. + - This option comes in handy if you want to match origins against a pattern, see the example below that matches subdomains of a specific namespace. +- Enable the `allow_any_origin` option. + + - Use this option if your supergraph is a public API with arbitrarily many web app consumers. + - With this option enabled, the router sends the [wildcard (`*`)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#directives) value for the `Access-Control-Allow-Origin` header. This enables any website to initiate browser connections to it (but they can't provide cookies or other credentials). + +- You must use the `origins` + `match_origins` option if clients need to [authenticate their requests with cookies](#passing-credentials). + +The following snippet includes an example of each option (use either `allow_any_origin`, or `origins + match_origins`): + +```yaml +cors: + # Set to true to allow any origin + # (Defaults to false) + allow_any_origin: true + + # List of accepted origins + # (Ignored if allow_any_origin is true) + # (Defaults to the GraphOS Studio url: `https://studio.apollographql.com`) + # + # An origin is a combination of scheme, hostname and port. + # It does not have any path section, so no trailing slash. + origins: + - https://www.your-app.example.com + - https://studio.apollographql.com # Keep this so GraphOS Studio can run queries against your router + match_origins: + - 'https://([a-z0-9]+[.])*api[.]example[.]com' # any host that uses https and ends with .api.example.com +``` + +You can also turn off CORS entirely by setting `origins` to an empty list: + +```yml +cors: + origins: [] +``` + +#### Passing credentials + +If your router requires requests to [include a user's credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#requests_with_credentials) (for example, via cookies), you need to modify your CORS configuration to tell the browser those credentials are allowed. + +You can enable credentials with CORS by setting the [`Access-Control-Allow-Credentials`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials) HTTP header to `true`. + + + +Your router must specify individual `origins` to support credentialed requests. If your router enables `allow_any_origin`, your browser will refuse to send credentials. + + + +To allow browsers to pass credentials to your router, set `allow_credentials` to `true`, like so: + +```yaml +cors: + origins: + - https://www.your-app.example.com + - https://studio.apollographql.com + allow_credentials: true +``` + +For examples of sending cookies and authorization headers from Apollo Client, see [Authentication](/react/networking/authentication/). + +#### All `cors` options + +The following snippet shows all CORS configuration defaults for your router: + +```yaml +# +# CORS (Cross Origin Resource Sharing) +# +cors: + # Set to true to allow any origin + allow_any_origin: false + + # List of accepted origins + # (Ignored if allow_any_origin is set to true) + # + # An origin is a combination of scheme, hostname and port. + # It does not have any path section, so no trailing slash. + origins: + - https://studio.apollographql.com # Keep this so GraphOS Studio can still run queries against your router + + # Set to true to add the `Access-Control-Allow-Credentials` header + allow_credentials: false + + # The headers to allow. + # Not setting this mirrors a client's received `access-control-request-headers` + # This is equivalent to allowing any headers, + # except it will also work if allow_credentials is set to true + allow_headers: [] + + # Allowed request methods + methods: + - GET + - POST + - OPTIONS + + # Which response headers are available to scripts running in the + # browser in response to a cross-origin request. + expose_headers: [] +``` + +#### Response `Vary` header + +A plugin may set a response `Vary` header. If, after all plugins are processed, there is no response `Vary` header, then the router will add one with a value of `origin`. + +### Subgraph error inclusion + +By default, your cloud supergraph redacts the details of subgraph errors in its responses to clients. The router instead returns a default error with the following message: + +``` +Subgraph errors redacted +``` + +This redaction prevents potential leaks of sensitive information to clients. + +If you instead want to propagate subgraph errors to clients, you can add the `include_subgraph_errors` key to your router's YAML configuration, like so: + +```yaml +include_subgraph_errors: + all: true # Propagate errors from all subraphs + subgraphs: + products: false # Do not propagate errors from the products subgraph +``` + +Any configuration under the `subgraphs` key takes precedence over configuration under the `all` key. In the example above, subgraph errors are included from all subgraphs except the `products` subgraph. + +### Introspection + +By default, your cloud supergraph does not resolve introspection queries. You can enable introspection like so: + +```yaml +# Do not enable introspection for production workloads! +supergraph: + introspection: true +``` diff --git a/docs/source/routing/cloud/custom-domains.mdx b/docs/source/routing/cloud/custom-domains.mdx new file mode 100644 index 0000000000..64b5613e3f --- /dev/null +++ b/docs/source/routing/cloud/custom-domains.mdx @@ -0,0 +1,72 @@ +--- +title: Custom Domains +subtitle: Use a custom subdomain for your cloud router endpoint +description: Use a custom domain for your cloud router endpoint to minimize client-side changes, use existing security policies, and shield against DDoS attacks. +redirectFrom: + - /graphos/cloud-routing/custom-domains +--- + + + +To interact with your supergraph, clients send requests to your router's endpoint. The _custom domains_ feature lets you replace the default `apollographos.net` router endpoint URL with your own subdomain. + +Custom domains can help to: + +- Minimize client-side changes +- Use your existing CORS policies and security controls +- Protect your cloud routers from DDoS attacks +- Provide TLS termination to your cloud routers + +## How custom domains work + +Custom domains use [CNAME records](https://www.cloudflare.com/learning/dns/dns-records/dns-cname-record/) to point requests made to your subdomain to your `apollographos.net` router endpoint URL. Custom domains run on [Cloudflare's](https://www.cloudflare.com/) global network. + +## Custom domains setup + +Setup includes two steps: + +1. Setting up a CNAME record in your DNS provider. +2. Opening a ticket with Apollo support to enable your CNAME. + + + +Custom domains will be available through self-service in GraphOS Studio later in 2024. In the meantime, you must open a support request to enable your CNAME with Apollo. + + + +### Setup a CNAME + +Create a CNAME record in your DNS provider that points to your Dedicated variant's [existing subdomain](/graphos/routing/cloud/dedicated-quickstart#router-endpoint-url). For example, create a CNAME for `api.mydomain.com` that points to `current--docs-example.apollographos.net`. + +You can find your Dedicated variant's subdomain in [GraphOS Studio](https://studio.apollographql.com?referrer=docs-content) on the **Cloud Router** page under **API Endpoint**. + +A cloud router's endpoint displayed on the Cloud Router page in GraphOS Studio + + + +CNAME records are assigned at the variant level, so you must set up a separate CNAME record for each graph variant that requires a custom domain. + + + +### Using an existing CNAME + +If you already have a CNAME record for the custom domain you want to use, [contact Apollo Support](#open-a-support-ticket) before making any changes. We'll guide you through remapping from a different host to the GraphOS Cloud subdomain. + +### Open a support ticket + +Next, open a support ticket requesting Apollo to enable your new CNAME. +You can open a ticket by emailing [support@apollographql.com](mailto:support@apollographql.com). Your request may take up to two business days to process. Apollo will notify you when your new CNAME is live. + +Your request may take up to two business days to process. Apollo will notify you when your new CNAME is live. + +## Limitations + +The custom domains feature doesn't support the following: + +- [Apex records](https://learn.microsoft.com/en-us/azure/dns/dns-zones-records#record-names) or [A records](https://learn.microsoft.com/en-us/azure/dns/dns-zones-records#record-types) +- Multiple custom domains per variant +- Load balancing traffic across multiple variants diff --git a/docs/source/routing/cloud/dedicated-quickstart.mdx b/docs/source/routing/cloud/dedicated-quickstart.mdx new file mode 100644 index 0000000000..6dafb026ce --- /dev/null +++ b/docs/source/routing/cloud/dedicated-quickstart.mdx @@ -0,0 +1,138 @@ +--- +title: Get Started with Cloud Dedicated +subtitle: Create your first Dedicated cloud router +description: Run a cloud router for your GraphQL APIs on dedicated infrastructure that Apollo provisions and manages. +--- + + + +Follow this hands-on guide to create a new graph that uses a Dedicated cloud router. +To learn about Dedicated cloud routing in general, go to the [Cloud Dedicated overview](/graphos/routing/cloud/dedicated). + +## Prerequisites + +To complete this quickstart, you must have the following: + +- A [GraphOS Studio](https://studio.apollographql.com?referrer=docs-content) account +- An organization with the Dedicated plan—get in touch to request access. +- One or more GraphQL APIs that Apollo can access. That means you must either: + - Make your GraphQL API(s) available via a publicly accessible URL, for example, `https://api.mycompany.com/subgraphA` + - Keep your GraphQL API(s) private but allow secure connections, for example, via [VPC networking](https://docs.aws.amazon.com/vpc/latest/peering/what-is-vpc-peering.html) + +If you have multiple subgraphs, each needs to be exposed to Apollo. Your supergraph, however, should only be publicly accessible via your cloud router. + + + +In a supergraph, each GraphQL API is called a _subgraph_. Apollo refers to these GraphQL APIs as subgraphs, even if you only connect one GraphQL API. + +The GraphOS Router doesn't supported nested federation—that is, a subgraph cannot act as a supergraph for another set of subgraphs. + + + +## Step 1. Create a new graph + +To provision a new Dedicated cloud router, you must first create a new graph in [GraphOS Studio](https://studio.apollographql.com?referrer=docs-content). To do so, click **Create New Graph** from the **Graphs** tab. + +Graphs tab in GraphOS Studio + +## Step 2. Connect APIs + +1. Next, connect your GraphQL API to Apollo. + + - If your API URL is publicly accessible, enter the API URL. This URL is the URL that client applications currently use to query your API. + - If your API isn't publicly accessible and requires private networking, you can connect to it with [AWS VPC Lattice](/graphos/routing/cloud/lattice-configuration). Select **My endpoint isn't publicly accessible** to connect a VPC. Follow the prompts to complete private subgraph setup. + +2. Enter a **Subgraph name**. The name should reflect your API's data or capabilities and uniquely identify your API among any other APIs you might add to the supergraph later. + + + + The subgraph name is immutable. + + + +3. Select the backend **provider** and **region** to deploy your cloud router in. +4. Optionally, configure headers, secrets, CORS rules, or other configurations. You can always [update your router configuration](#step-3-inspect-and-configure-your-cloud-router) as needed. +5. Provide a **Supergraph name** and **ID**. + + - The supergraph name is displayed throughout Studio and helps your team distinguish between your graphs. You can change your graph's name at any time. + - The ID is immutable and must be unique across all of Apollo. Ensure it starts with a letter and contains only letters, numbers, and dashes. You'll use the ID to reference your graph from various tools, such as the Rover CLI. + +6. Click **Create GraphOS Router**. + +Provisioning a router for your new supergraph may take a few moments. Once done, click **Query your supergraph** to open the Explorer and begin playing with your graph, or **Open README** to go to your graph's landing page. + +Before moving to the next step, add any other GraphQL APIs you want to connect. Open the **Subgraphs** page from the left navigation and click **Add a subgraph**. + +The 'Add a subgraph' button in the subgraphs page in GraphOS Studio + +Every router configuration or supergraph schema change—including adding a subgraph—triggers a new [launch](/graphos/delivery/launches/). Every launch automatically deploys new cloud router instances for your supergraph. + + + +The launch process typically takes 1-2 minutes but may take up to 5 minutes. During the process, Apollo provisions new GCUs and swaps them in once they're online. Deployments minimize API degradation and downtime. + + + +## Step 3. Inspect and configure your cloud router + +Dedicated cloud routers have a separate UI for management and configuration. Open the **Cloud Router** page from the left navigation. This page shows a summary of your cloud router, including its **API endpoint** and **API details**. + +Use the **Configuration** tab to manage your cloud router's configuration, including **Secrets** and **Router configuration YAML**. See the [router docs](/router/configuration/overview) for more information. + +The Cloud Router page in GraphOS Studio + +## Step 4. Test and validate + +To test whether your graph works as intended, run a sample query by clicking **Run in Explorer** from your graph's **README** page. + +[Enable subgraph error reporting](/graphos/routing/cloud/lattice-troubleshooting/#enable-subgraph-error-inclusion) if you run into issues. + +For further testing, you can add variants to your graph for development or staging environments. To do so, go to **Settings** > **This Graph** > **Variants** and click **Add a variant**. + +Apollo recommends running a [load test](/graphos/routing/cloud/throughput-guide#load-testing) to determine how much [throughput capacity](/graphos/routing/cloud/throughput-guide) you need to run your graph. + +## Step 5. Go live + +Your supergraph is ready to start receiving client operations! If you have existing client applications that connect directly to your GraphQL API, you can update their GraphQL endpoint URL to your router's URL. + +Similarly, any new client applications should use your router's URL. + + + +- For all browser-based clients, make sure their origin is allowed in your router's [CORS rules](#cors-rules). + +- Only update clients that communicate with the correct instance of your GraphQL API. For example, if your API has staging and production instances, only update clients that communicate with the instance used by this supergraph variant. + + + +#### Router endpoint URL + +You can find your endpoint URL on the **Cloud router** page in GraphOS Studio. + +A cloud router's endpoint displayed on the Cloud Router page in GraphOS Studio + + + +By default, cloud router URLs are on a subdomain of `apollographos.net`. You can setup a [custom domain](/graphos/routing/cloud/custom-domains) to minimize client-side changes. + + + +## Next steps + +Congratulations! 🎉 You've built a cloud supergraph on GraphOS. Check out the general Quickstart's [Next steps](/graphos/get-started/guides/quickstart#next-steps) for some of the most common and important features to learn about. diff --git a/docs/source/routing/cloud/dedicated.mdx b/docs/source/routing/cloud/dedicated.mdx new file mode 100644 index 0000000000..b07c8673df --- /dev/null +++ b/docs/source/routing/cloud/dedicated.mdx @@ -0,0 +1,52 @@ +--- +title: Cloud Dedicated Overview +subtitle: Learn about the Dedicated cloud router offering and pricing +description: Learn about Apollo's dedicated cloud routing for GraphQL APIs including available AWS regions and pricing. +--- + + + +GraphOS _Cloud Dedicated_ is the Apollo offering that lets you run a cloud router on dedicated, pre-provisioned infrastructure that you control and scale. It gives you access to a fully managed and monitored fleet of GraphOS Routers. + +The Cloud Dedicated approach lets you implement and scale your supergraph without managing any additional infrastructure. Tailored for teams handling production-grade workloads, Cloud Dedicated offers additional control over performance and security. + + + +Go the [Cloud Dedicated quickstart](/graphos/routing/cloud/dedicated-quickstart) to get started. + + + +## Runs on AWS + +Cloud Dedicated runs a fleet of GraphOS Routers in the AWS region of your choice. The following regions are currently available: + +- us-east-1 +- us-east-2 +- us-west-2 +- ap-southeast-1 +- ap-southeast-2 +- ap-northeast-1 +- ca-central-1 +- eu-central-1 +- eu-west-1 +- eu-west-2 +- eu-north-1 + +Dedicated supports subgraphs running in any cloud region or provider. However, you may incur additional networking charges for subgraphs running outside your selected AWS region. AWS VPC Lattice is only supported for the regions listed above. + +## Pricing + +Cloud Dedicated pricing is based on the amount of _Graph Compute Units_ (GCUs) needed to run your graph. A GCU is a unit of throughput capacity. You can scale GCUs via [GraphOS Studio](https://studio.apollographql.com?referrer=docs-content) or the [GraphOS Platform API](/graphos/reference/platform-api/). + +To learn about GCU performance and scaling, consult the [Throughput guide](/graphos/routing/cloud/throughput-guide). + +## Private preview + +Cloud Dedicated is a new product and is in [preview](/graphos/reference/feature-launch-stages/#preview) while it matures. It is only available to select customers on an invite-only basis. If you have feedback or are interested in joining the preview, get in touch. + +Please note the following while Cloud Dedicated is in preview: + +- 99.9% SLA for ingress traffic +- Limited to customers running subgraphs in AWS +- Month-to-month billing, pricing subject to change +- Limited scaling, up to 10 GCUs per variant diff --git a/docs/source/routing/cloud/index.mdx b/docs/source/routing/cloud/index.mdx new file mode 100644 index 0000000000..0d6111cf8f --- /dev/null +++ b/docs/source/routing/cloud/index.mdx @@ -0,0 +1,166 @@ +--- +title: Cloud Routing +subtitle: Cloud-hosted routers for cloud supergraphs +--- + + + +Apollo has paused new sign-ups for Serverless and Dedicated plans while we improve our offerings based on user feedback. This means cloud routing is temporarily unavailable to new users. In the meantime, you can explore other GraphOS features with a [free trial](https://studio.apollographql.com/signup?referrer=docs-content). + + + +When you create a cloud supergraph, GraphOS provisions and manages a _cloud router_. Routers act as entry points to your GraphQL APIs. Individual GraphQL APIs are called _subgraphs_ in this architecture. + +```mermaid +flowchart LR; + clients(Clients); + subgraph "GraphOS Cloud" + router(["Cloud router"]); + end; + subgraph YourInfra["Your infrastructure"]; + subgraphA[Subgraph A]; + subgraphB[Subgraph B]; + end; + clients -.- router; + router --- subgraphA & subgraphB; + classDef padding padding-left:1em, padding-right:1em + YourInfra:::padding + class clients secondary; +``` + +Clients send operations to your router's public endpoint instead of your subgraphs. + +GraphOS only hosts the runtime for your supergraph's cloud router. GraphQL servers for your subgraphs are still hosted in your infrastructure. + +

+ + Create your first cloud supergraph + +

+ +## Federation and subgraph compatibility + +Cloud supergraphs use [Apollo Federation 2](/federation/) for their core architecture. [Many GraphQL server libraries](/graphos/reference/federation/compatible-subgraphs) support Federation 2. Your GraphQL API doesn't already need to be using Apollo Federation to add it to a cloud supergraph. + +## Cloud router types and availability + +Cloud supergraphs are only available to organizations with Serverless and Dedicated plans**. +Serverless cloud routers run on shared infrastructure. Dedicated cloud routers run on dedicated infrastructure that you control and scale. +Cloud routers aren't available with Enterprise or legacy Free or Team plans. + + + +**We've paused new sign-ups for Serverless and Dedicated plans while we improve our offerings based on user feedback. In the meantime, you can explore GraphOS features with a [free trial](https://studio.apollographql.com/signup?referrer=docs-content). + + + +## Cloud router regions + +Serverless cloud routers are hosted in the us-east-1 AWS region. Dedicated cloud routers have a wider [variety of options](/graphos/routing/cloud/dedicated/#runs-on-aws). Region selection for cloud routers is only available on the Dedicated plan. Contact Sales to learn more. +You can view a cloud router's region on its graph's **Overview** page under **Cloud Router Details**. + +Variant overview page in GraphOS Studio + +## Cloud router status + +Cloud routers can have the following statuses: + +| Status | Description | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Initializing** | Your cloud router is being created. This process may take up to five minutes. [Learn more.](#initializing) | +| **Running** | Your graph is operating normally. | +| **Error** | Your cloud router is running, but a deployment recently failed. For more information on the failure, see the **Launches** page in GraphOS Studio. | + + + +Serverless routers have additional statuses, including **Sleeping** and **Deleted**. Learn more on the [Serverless overview page](/graphos/routing/cloud/serverless/#serverless-router-status). + + + +You can see your cloud router's status in GraphOS Studio on the associated graph's **Overview** page under **Cloud Router Details**. + +### Initializing + +Apollo provisions a router whenever you create a cloud supergraph in GraphOS Studio or whenever you create a new variant for an existing cloud supergraph. Each variant has its own distinct router. + +When you first create a variant, the router provisioning process can take a few minutes. While this process completes, an **INITIATING ENDPOINT** label appears at the top of the variant's page in Studio: + +Label in Studio indicating a router hasn't finished provisioning + +Once initialized, you can [configure your cloud router](/graphos/routing/cloud/configuration). + +## Cloud launches + +Publishing a new subgraph schema or editing a cloud router's config triggers a new [launch](/graphos/delivery/launches/). Every launch automatically deploys new router instances for your graph. You can see a launch's details, including possible failures, from a graph's **Launches** page in GraphOS Studio. + + + +A router deployment might fail due to a platform incident or schema composition issues. To resolve this, try republishing your subgraph schema. + + + +## Router version updates + +Apollo manages the Apollo Router Core version deployed to cloud routers. It ensures that newly released versions are deployed within 30 days of release. Some minor and patch versions may be skipped. + +Router releases go through rigorous testing before deployment on GraphOS Cloud. An Apollo engineer oversees deployment. If any cloud routers fail to boot up, they roll back to a previous version. While some edge cases may arise—for example, a query planner update could result in slightly degraded performance—router updates should not disrupt your supergraphs. + + + +Opting out of router updates to cloud routers isn't currently supported. + + + +## Security and compliance + +The entire GraphOS platform, including its cloud routing infrastructure, is SOC 2 Type 2 certified. +Secrets are encrypted both in transit and at rest. +Secrets are only available inside the runtime environment. You have total control over when those secrets are resolved in configuration. + +The Apollo Router Core (the underlying technology for cloud routing) has been [tested and audited by Doyensec](https://doyensec.com/resources/Doyensec_Apollo_Report_Q22022_v4_AfterRetest.pdf). + +### GraphOS Cloud on AWS + +GraphOS Cloud on AWS is a managed API solution. It runs the GraphOS Router on AWS infrastructure to provide a high-performance, configurable GraphQL router. + +[Download an overview of GraphOS Cloud on AWS security and compliance practices](https://www.apollographql.com/trust/request-security-report). +For more information on Apollo's compliance and security measures, visit the [Trust Center](https://www.apollographql.com/trust/compliance-and-security). + +### Which types of data are collected by a cloud supergraph? + +A cloud supergraph uses a GraphOS Router to execute operations across one or more subgraphs hosted in your infrastructure: + +```mermaid +flowchart LR; + clients(Clients); + subgraph "GraphOS"; + router(["Router"]); + end; + subgraph "Your infrastructure"; + subgraphA[Subgraph A]; + subgraphB[Subgraph B] + router --- subgraphA + router --- subgraphB + end; + clients -.- router; + class clients secondary; +``` + +Each instance of GraphOS Router runs in its own managed container. These instances use the same mechanisms to report operation metrics to GraphOS as a GraphOS Router or Apollo Router Core instance running in any other environment. The only difference is that metrics reporting is always enabled for a cloud supergraph's router. + +GraphOS Routers do not persist or log any response data returned by your subgraphs. They only assemble this data into responses for requesting clients. diff --git a/docs/source/routing/cloud/lattice-configuration.mdx b/docs/source/routing/cloud/lattice-configuration.mdx new file mode 100644 index 0000000000..bbd0a32dc8 --- /dev/null +++ b/docs/source/routing/cloud/lattice-configuration.mdx @@ -0,0 +1,348 @@ +--- +title: Amazon VPC Lattice Configuration +subtitle: Securely communicate with subgraphs on your Amazon VPC +description: Configure Amazon VPC Lattice to send traffic to and receive traffic from your Apollo GraphOS cloud router. +redirectFrom: + - /graphos/cloud-routing/lattice +--- + + + +Cloud Dedicated uses [Amazon VPC Lattice](https://aws.amazon.com/vpc/lattice/) to send traffic to subgraphs running in an Amazon VPC without exposing them to the internet. + +```mermaid +flowchart LR; + clients(Clients); + subgraph "Apollo Cloud"; + router(["Cloud
router"]); + end; + subgraph "Amazon Virtual Private Cloud" + lattice[Amazon VPC
Lattice service] + service1[Subgraph 1]; + service2[Subgraph 2]; + service3[Subgraph 3]; + end; + + router --> lattice + lattice --> service1 & service2 & service3; + + clients -->|Requests| router; +``` + +This guide shows how to create Lattice services and share them with GraphOS. This configuration lets your GraphOS cloud routers securely communicate with your private subgraphs. + + + +Using Amazon VPC Lattice incurs costs outside of your GraphOS Dedicated spend. Refer to the [Lattice pricing page](https://aws.amazon.com/vpc/lattice/pricing/) to learn more. + + + + +## How GraphOS ensures subgraph security through Lattice + +When you first share Lattice services with GraphOS, it scans the Lattice services to retrieve their ARNs and domain names. +Then, when you add a private subgraph to a cloud supergraph, GraphOS checks that the subgraph's domain matches one of the Lattice services associated with your GraphOS organization. + +As a second line of defense, supergraphs use AWS IAM permissions and SigV4 to only allow traffic to subgraphs in the same GraphOS organization. + +## Configuration overview + +To allow GraphOS cloud routers to send traffic to private subgraphs in an Amazon VPC, you must: + +1. Create a Lattice target group for each subgraph hosted in your Amazon VPC. +2. Create a Lattice service for each graph variant in GraphOS. +3. Share your Lattice service(s) with the Apollo AWS Organization via a resource share. +4. Link the resource share in GraphOS Studio. + +This guide offers instructions for each step. + +You can also use the [Apollo Terraform module](https://github.com/apollographql/terraform-graphos-aws) to provision Lattice target groups, services, and resource shares. +The module completes steps 1 - 3 of this configuration guide. Once you've set it up, you can skip to [step 4](#step-4-link-resource-share)—linking the provisioned resource share in GraphOS Studio. +Refer to the [module's README](https://github.com/apollographql/terraform-graphos-aws#apollo-graphos-cloud-private-subgraphs-module) for more information. + + + +- You can use Amazon VPC Lattice in your organization for other uses than routing GraphOS traffic to subgraphs. A Lattice service can be associated with multiple service networks, and GraphOS associates your Lattice services with its own service network. +- You can only use Lattice for subgraphs in the same AWS region as your cloud router. If you need to run subgraphs in different AWS regions or run your workloads in a region not yet supported by Dedicated, please get in touch. + + + +## Step 1. Create a target group + +A VPC Lattice _target group_ is a collection of targets, or compute resources, that run your application or service. +In the GraphOS context, a target group maps to a subgraph. +If you have multiple subgraphs, repeat these steps for each subgraph. + + +1. In the AWS Console for your region of choice, go to the VPC service page: + +- [US East (N. Virginia) - us-east-1](https://us-east-1.console.aws.amazon.com/vpc/home?region=us-east-1) +- [Europe (Ireland) - eu-west-1](https://eu-west-1.console.aws.amazon.com/vpc/home?region=eu-west-1) + +2. In the left navigation, scroll down and open **VPC Lattice > Target groups**. +3. Click **Create target group** on the top right. +4. In the **Basic configuration** section, set the properties that match your subgraph resources. + + Amazon VPC service page + +5. (Optional) If you use a target type with health checks, ensure you configure your health checks. Otherwise, Lattice can't send traffic to your subgraphs. +6. Register the targets based on your chosen target type. For example, if you selected **IP addresses** as your target type, add each IP address. + + Amazon VPC service page + +7. Review your targets to make sure all information is correct. +8. Click **Create target group** at the bottom right corner of the page. + +Congratulations! You've created an Amazon VPC Lattice target group. +Repeat this process for each subgraph you want to share with GraphOS. + +## Step 2. Create a Lattice service + +In Lattice, a _service_ represents a self-contained software module. +A VPC Lattice service has a listener that uses rules, called listener rules, that you can configure to help route traffic to your targets. +In this step, you create a single VPC Lattice service with listener rules for each of your target groups. + +In the GraphOS context, a Lattice service maps to a graph variant. +Create one service for each of your variants. + +1. In the AWS Console for your region, go to the VPC service page: + +- [US East (N. Virginia) - us-east-1](https://us-east-1.console.aws.amazon.com/vpc/home?region=us-east-1) +- [Europe (Ireland) - eu-west-1](https://eu-west-1.console.aws.amazon.com/vpc/home?region=eu-west-1) + +2. In the left navigation, scroll down and open **VPC Lattice > Services**. +3. Click **Create service** in the top right. +4. In the **Identifiers** section, enter a descriptive name for the service. Optionally, enter a description and tags. + + Amazon VPC service page + +5. In the **Custom domain configuration** section, leave **Specify a custom domain configuration** unchecked. +6. In the **Service access** section, select the **AWS IAM** authentication type and paste the following authorization policy. This policy ensures that only the Apollo AWS Organization can send traffic to your subgraphs. + + ```json showLineNumbers=false + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": "*", + "Action": "vpc-lattice-svcs:Invoke", + "Resource": "*", + "Condition": { + "ForAnyValue:StringLike": { + "aws:PrincipalOrgPaths": "o-9vaxczew6u/*/ou-leyb-l9pccq2t/ou-leyb-fvqz35yo/*" + } + } + } + ] + } + ``` + +7. (Optional) For extra security, you can audit all the traffic coming to your subgraph by enabling **Access logs** in the **Monitoring** section. +8. Once you've configured the service, click **Next** on the bottom right of the page. +9. Define routing information to the target group you created in [Step 1](#step-1-create-lattice-target-group). Set the protocol to **HTTPS** and the port to **443**. + + + + For security reasons, Apollo requires you to use HTTPS for your listener. Using HTTPS enforces encryption in transit of the traffic between your GraphOS cloud router and your Lattice service. + + + + Amazon VPC service page + +10. If you have multiple target groups, add a **Listener rule** for each target group. + + Amazon VPC service page + +11. Click **Next** at the bottom right of the page once you've configured your listener. +12. Don't select a VPC Lattice service network. Your subgraphs will integrate with a service network managed by Apollo. Instead, click the **Next** button at the bottom right of the page. +13. Ensure the information you've entered is correct. Then click **Create VPC Lattice service** at the bottom right of the page. + +Congratulations! You've now created a Lattice service with listeners for your subgraphs. + +## Step 3. Share Lattice service + +For GraphOS to access your Lattice service, you must share it with the Apollo AWS organization. +You do this through a _resource share_ in AWS Resource Access Manager (AWS RAM). +A resource share specifies the resources to share and the consumers with whom to share them. + +```mermaid +flowchart LR; + apollo(Apollo Cloud) + subgraph "Amazon Virtual Private Cloud" + lattice[Amazon VPC
Lattice service] + service1[Subgraph 1]; + service2[Subgraph 2]; + service3[Subgraph 3]; + end; + + apollo-. AWS RAM
resource share .- lattice + lattice --> service1 & service2 & service3; +``` + +If you have multiple Lattice services, you can share them all through one resource share. + +1. In the AWS Console for your region of choice, go to the Resource Access Manager service page: + +- [US East (N. Virginia) - us-east-1](https://us-east-1.console.aws.amazon.com/ram/home?region=us-east-1) +- [Europe (Ireland) - eu-west-1](https://eu-west-1.console.aws.amazon.com/ram/home?region=eu-west-1) + +2. In the left navigation, scroll down and open **Shared by me > Resource shares**. +3. Click **Create resource share** in the top right corner. +4. In the **Resource share name** section, enter a name for your resource share. +5. In the **Resources section**, select the **VPC Lattice Services** resource type. +6. Select all the Lattice services that contain subgraphs. + + Amazon VPC shared resources page + +7. (Optional) Set tags for your resource share. +8. Click the **Next** button at the bottom right corner of the page. +9. Verify that the **Managed permissions** give access to associate the Lattice services with a service network (`vpc-lattice:CreateServiceNetworkServiceAssociation` and `vpc-lattice:GetService`). Then click the **Next** button at the bottom right of the page. + + Amazon VPC shared resources page + +10. In the **Principals** section, select **Allow sharing with anyone** with a **principal type** of `AWS account`. Enter the following value for the account ID: `282421723282`, then click the **Add** button. + + Amazon VPC shared resources page + +11. Confirm that `282421723282` is the only selected principal for this resource share, then click the **Next** button on the bottom right corner. +12. Confirm that all the information is correct, then click **Create resource share** at the bottom right of the page. + +Congratulations! You've now shared your Lattice service(s) with Apollo's AWS organization. + +The last step is associating your resource share with a graph in GraphOS. + + + +- You have 12 hours to associate your resource share. Otherwise, AWS RAM will fail to process the invitation, and you must restart this step. +- For security purposes, we recommend you continue to the next step immediately after creating the resource share. If you see that the resource share was **Accepted** or **Failed** in the AWS console and you didn't follow [step 4](#step-4-link-resource-share) of this guide, follow the steps to [remove access to private subgraphs](/graphos/routing/cloud/lattice-management#remove-access) and restart this step. + + + +## Step 4. Link resource share + +At this point, you've shared your Lattice service(s) with the Apollo AWS organization. In this step, you link each service to a particular cloud router in GraphOS Studio. +The cloud router can then route client requests. + +```mermaid +flowchart LR; + clients(Clients); + subgraph "Apollo Cloud"; + router(["Cloud
router"]); + end; + subgraph "Amazon Virtual Private Cloud" + lattice[Amazon VPC
Lattice service] + service1[Subgraph 1]; + service2[Subgraph 2]; + service3[Subgraph 3]; + end; + + router --> lattice + lattice --> service1 & service2 & service3; + + clients -->|Requests| router; +``` + +1. In the AWS Console for your region of choice, go to the Resource Access Manager service page: + +- [US East (N. Virginia) - us-east-1](https://us-east-1.console.aws.amazon.com/ram/home?region=us-east-1) +- [Europe (Ireland) - eu-west-1](https://eu-west-1.console.aws.amazon.com/ram/home?region=eu-west-1) + +2. In the left navigation, scroll down and open **Shared by me > Resource shares**. +3. Click the resource share you created in the previous step. +4. Copy the **ARN** for the resource share. + + Amazon VPC resource share page + +The next steps differ depending on whether you're creating a [new graph](#setup-for-new-graphs) in GraphOS or adding this [service to an existing graph](#setup-for-existing-graphs). + +### Setup for new graphs + +1. Go to [GraphOS Studio](https://studio.apollographql.com?referrer=docs-content). +2. Click the **Create New Graph** tab at the top right of the screen. +3. Follow Studio's onboarding steps to create a graph with a new private subgraph. +4. When prompted to **Provide your GraphQL API endpoint**, select **My endpoint is not directly accessible** at the bottom of the page. +5. Choose the backend provider you want to use for your private subgraph and the region where your subgraph should be provisioned. + + + + All private subgraphs connected to a GraphOS cloud router must be in the same region. + + + +6. Paste the ARN of the resource share you created and copied from your AWS Console, then click **Link my Resource** and **Next** to continue. +7. From the dropdown menu, select the Lattice service that you want to connect to your GraphOS router. The URL automatically appends a default path of `/api/graphql`, but you can change this path if you want to. +8. Add a **Service Name** to describe your Lattice service. GraphOS Studio uses this name to identify your Lattice service. +9. Paste the GraphQL schema for this subgraph in the **Schema** field. You can also upload a schema file by clicking the **Upload Schema** button. + + + +When your AWS resource is set to private, it isn't accessible by external services by default. This ensures a high level of security for your data, but it also means extra steps are needed to enable communication between your resource and our system. GraphOS needs your GraphQL API's schema so it can generate the correct queries and mutations to send to your subgraph. + + + +10. Update the ID and the name of the supergraph that you want to add this private subgraph to. An ID and name are automatically generated based on your GraphOS organization's name, but you can change both as needed. +11. To finish, click **Create GraphOS Router**. + +Congratulations! You've now created a GraphOS cloud router with a private subgraph. + +### Setup for existing graphs + +1. Go to the graph you want to connect in [GraphOS Studio](https://studio.apollographql.com?referrer=docs-content). +2. From the left sidebar, open the **Subgraphs** tab of your graph. +3. Click **Add a Subgraph** on the right of the page. +4. In the dialog, select the **Private** option, then select the AWS service you want to add from the dropdown menu. The URL automatically appends a default path of `/api/graphql`, but you can change this path if you want to. +5. Add a **Service Name** to describe your Lattice service. GraphOS Studio uses this name to identify your Lattice service. +6. Paste the GraphQL schema for this subgraph in the **Schema** field. You can also upload a schema file by clicking the **Upload Schema** button. + + + +When your AWS resource is set to private, it isn't accessible by external services by default. This ensures a high level of security for your data, but it also means extra steps are needed to enable communication between your resource and our system. GraphOS needs your GraphQL API's schema so it can generate the correct queries and mutations to send to your subgraph. + + + +7. To finish, click **Add Subgraph**. + +Congratulations! You've now added a private subgraph to your GraphOS cloud router. + +## Next steps + +After you've linked your VPC Lattice services with your cloud router, you may want to set up monitoring. +The [Lattice management page](/graphos/routing/cloud/lattice-management) provides information on monitoring and how to further restrict and remove access to subgraphs. +See the [troubleshooting guide](/graphos/routing/cloud/lattice-troubleshooting) if you're having issues with your Lattice setup. \ No newline at end of file diff --git a/docs/source/routing/cloud/lattice-management.mdx b/docs/source/routing/cloud/lattice-management.mdx new file mode 100644 index 0000000000..86c577a401 --- /dev/null +++ b/docs/source/routing/cloud/lattice-management.mdx @@ -0,0 +1,181 @@ +--- +title: Amazon VPC Lattice Management +subtitle: Monitor, restrict, and remove access to subgraphs +description: Manage your Apollo GraphOS cloud router with Amazon VPC Lattice to monitor, restrict, and remove access to subgraphs. +redirectFrom: + - /graphos/cloud-routing/lattice-management +--- + + + +This guide covers: + +- How to monitor traffic flowing through Amazon VPC Lattice to your subgraphs. +- How to add access restrictions to your subgraphs +- How to remove GraphOS access to your subgraphs + + + +If you haven't configured Amazon VPC Lattice yet or need to add new subgraphs, follow the [configuration guide](/graphos/routing/cloud/lattice-configuration). + + + +## Amazon VPC Lattice monitoring + +To confirm that traffic is flowing to your private subgraphs, you can use the metrics and access logs emitted by Amazon VPC Lattice: + +1. In the AWS Console for your region of choice, go to the VPC service page. +2. In the left navigation, scroll down and open **VPC Lattice > Services**. +3. Click the Lattice service used by the subgraph in question. +4. Click the **Monitoring** tab. + +From there, you can configure and enable access logs for your Amazon VPC Lattice service. + +Amazon VPC Lattice access logs + +Use the **Metrics** tab to get a quick overview of traffic flowing to your private subgraphs. + +Amazon VPC Lattice metrics + +You can also use [Amazon CloudWatch metrics emitted by Amazon VPC Lattice](https://docs.aws.amazon.com/vpc-lattice/latest/ug/monitoring-cloudwatch.html) to set up dashboards and alarms to understand the health of your private subgraphs. + +## Further restrict access + +Once you configure an Amazon VPC Lattice service to accept traffic from GraphOS, it's protected by multiple security layers: + +- The Amazon VPC Lattice service network only allows traffic with a valid signature over HTTPS. +- The Lattice service's configured authorization policy allows traffic only from Apollo AWS accounts. (This is the authorization policy you configured in step 6 [when creating your Lattice service](/graphos/routing/cloud/lattice-configuration#step-2-create-a-lattice-service).) +- GraphOS cloud router provisioning compares subgraphs in a supergraph's configuration against the list of known private subgraphs in its Apollo account. It refuses to create or update cloud routers with unknown private subgraphs. +- Cloud routers can only invoke private subgraphs listed in their supergraph configuration. + +You can further restrict access to your private subgraphs by configuring additional [conditions](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html) in your service's authorization policy. +Specifically, you can add conditions to restrict traffic based on your organization's Apollo account ID or your supergraph's graph ref. + +### Update Lattice service authorization policy + +To update a Lattice service's authorization policy, you first need the **Apollo account ID** and/or **graph ref** to which you want to restrict subgraph access. + +#### Get account ID and graph ref + +- Reach out to your Apollo contact to get your account ID. Specify that you need the account ID to update your Lattice service's authorization policy. + + + + The Apollo account ID you specify in your authorization policy isn't the GraphOS organization ID you can find in GraphOS Studio. + + + +- You can find your supergraph's graph ref in your Apollo account: + - Log in to [GraphOS Studio](https://studio.apollographql.com?referrer=docs-content). + - Click on a graph variant on the **Graphs** page. The graph ref is at the top of the page. + +If you want to provide subgraph access to multiple supergraphs or GraphOS accounts, specify multiple graph refs and account IDs when updating your policy. + +#### Update policy + +If you are using the [Apollo Terraform module](https://github.com/apollographql/terraform-graphos-aws), you can set the [`apollo_account_ids` and `apollo_graph_refs` variables](https://github.com/apollographql/terraform-graphos-aws#usage) to update your authorization policy. Provide one or more Apollo account IDs or graph refs: + +```txt showLineNumbers=false disableCopy=true +apollo_account_ids = ["my_account_id", "another_account_id"] +apollo_graph_refs = ["my-graph@my-variant", "another-graph@my-variant"] +``` + +If you aren't using the Apollo Terraform module, follow these steps: + +1. In the AWS Console for your region of choice, go to the VPC service page: + +- [US East (N. Virginia) - us-east-1](https://us-east-1.console.aws.amazon.com/ram/home?region=us-east-1) +- [Europe (Ireland) - eu-west-1](https://eu-west-1.console.aws.amazon.com/ram/home?region=eu-west-1) + +2. In the left navigation, scroll down and open **Services** in the **VPC Lattice** section. +3. Click the Lattice service whose authorization policy you want to configure. +4. In the **Service access** section, update your authorization policy. You can use the following as an example—make sure to replace the account ID and graph ref with your own. + +```json {13-17} showLineNumbers=false +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": "*", + "Action": "vpc-lattice-svcs:Invoke", + "Resource": "*", + "Condition": { + "ForAnyValue:StringLike": { + "aws:PrincipalOrgPaths": "o-9vaxczew6u/*/ou-leyb-l9pccq2t/ou-leyb-fvqz35yo/*" + }, + // Restrict traffic based on Apollo account IDs or graphRefs + "StringEquals": { + "aws:PrincipalTag/Apollo:accountId": "my_account_id_xezf34", + "aws:PrincipalTag/Apollo:graphRef": "my-graph@my-variant" + } + } + } + ] +} +``` + +If multiple supergraphs should have access to the subgraph, use a comma-separated string of graph refs for `aws:PrincipalTag/Apollo:graphRef`. For example: + +```json showLineNumbers=false disableCopy=true +"aws:PrincipalTag/Apollo:graphRef": "my-graph@my-variant, my-graph@another-variant, another-graph@another-variant" +``` + +Similarly, you can use a comma-separated string of account IDs for `aws:PrincipalTag/Apollo:accountId`: + +```json showLineNumbers=false disableCopy=true +"aws:PrincipalTag/Apollo:accountId": "my_account_id_xezf34", "my_account_id_dehs56" +``` + +## Remove access + +To remove GraphOS access to private subgraphs, you must remove both resource shares and service network associations. +Keep in mind that any existing supergraphs that send traffic to your private subgraphs will stop working once you remove access. + +### Remove resource shares + +1. In the AWS Console for your region of choice, go to the Resource Access Manager service page: + +- [US East (N. Virginia) - us-east-1](https://us-east-1.console.aws.amazon.com/ram/home?region=us-east-1) +- [Europe (Ireland) - eu-west-1](https://eu-west-1.console.aws.amazon.com/ram/home?region=eu-west-1) + +2. In the left navigation, click **Resource shares** in the **Shared by me** section. +3. Select the resource share(s) associated with the Apollo AWS organization. Then click the **Delete** button in the top right corner. +4. Click **Delete** in the dialog that appears. + +### Remove service network associations + +1. In the AWS Console for your region of choice, go to the VPC service page: + +- [US East (N. Virginia) - us-east-1](https://us-east-1.console.aws.amazon.com/ram/home?region=us-east-1) +- [Europe (Ireland) - eu-west-1](https://eu-west-1.console.aws.amazon.com/ram/home?region=eu-west-1) + +2. In the left navigation, scroll down and open **Services** in the **VPC Lattice** section. +3. Click the Lattice service you want to disconnect. +4. In the **Service network associations**, select the **graphos-cloud** service name. + +Amazon VPC service page + +5. Click the **Actions** button in the top right of that section. Then, click **Delete network associations**. + +Amazon VPC service page + +6. Follow the confirmation instructions and click **Delete**. + +Deleting the network association can take a few seconds. Once you delete the network association, GraphOS can no longer contact your subgraphs. diff --git a/docs/source/routing/cloud/lattice-troubleshooting.mdx b/docs/source/routing/cloud/lattice-troubleshooting.mdx new file mode 100644 index 0000000000..89f8127c5d --- /dev/null +++ b/docs/source/routing/cloud/lattice-troubleshooting.mdx @@ -0,0 +1,135 @@ +--- +title: Lattice Troubleshooting Guide +subtitle: Troubleshoot common issues and errors with Amazon VPC Lattice +description: Troubleshoot common issues and errors with Amazon VPC Lattice and an Apollo Cloud Dedicated router +redirectFrom: + - /graphos/cloud-routing/lattice-troubleshooting +--- + + + +Refer to the [configuration page](/graphos/routing/cloud/lattice-configuration) to learn how to configure AWS VPC Lattice to send traffic to your subgraphs. + +## Enable subgraph error inclusion + +To help resolve AWS VPC Lattice connection issues, enable subgraph error inclusions for your graph variant. This configuration lets you see error messages generated by your subgraphs. Follow these steps to set the configuration: + +1. Go to [GraphOS Studio](https://studio.apollographql.com?referrer=docs-content). +2. Open the **Cloud Router** page from the left navigation. +3. Open the **Configuration** tab. +4. In **Router configuration YAML**, ensure your configuration has the following configuration block: + +```yaml +include_subgraph_errors: + all: true +``` + +5. Click the **Save** button in the top right corner of that section. + +Configuration changes trigger a new launch. Please wait a few minutes for your cloud router to update with this new configuration. You can track your graph variant's deployment status on its **Launches** page. + +Once you've found and resolved the issue, Apollo recommends turning off subgraph error inclusion. To do so, remove the `include_subgraph_errors` configuration. Then, save the router's configuration YAML. + +## Common issues and errors + +If you encounter an error not listed below and need help, don't hesitate to get in touch with your Apollo contact. We're here to help. + +### Overriding `host` headers + +Amazon VPC Lattice relies on the `host` header to secure and route requests. You can't change this header on Cloud Dedicated. Instead, consider using a header like `x-host`. You can rewrite an incoming header through your [router configuration](/graphos/routing/cloud/dedicated-quickstart#step-3-inspect-and-configure-your-cloud-router) YAML: + +```yaml title="router.yaml" +# ...other configuration... +headers: + all: # Header rules for all subgraphs + request: + - propagate: + named: 'host' + rename: 'x-host' +``` + +The previous example renames a `host` header to `x-host`. + +### Service in resource share doesn't appear in private subgraphs + +Cloud Dedicated doesn't automatically scan your resource shares for new Lattice services. [Adding a subgraph](/graphos/routing/cloud/lattice-configuration#setup-for-existing-graphs) or [creating a new graph](/graphos/routing/cloud/lattice-configuration#setup-for-new-graphs) automatically triggers a scan for new Lattice services. If you can't view the latest resource shares for your graph, please get in touch for additional support. + +### Providing `Authorization` headers + +Because AWS Sigv4 relies on the [HTTP `Authorization` request header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) for [signing requests](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-auth-using-authorization-header.html), you may receive an error like this: `You must be authenticated to access this resource. Please provide a valid Bearer Token in the Authorization header.` + +If your subgraphs rely on the `Authorization` header for authentication, your router must [rename](/graphos/routing/header-propagation/#propagate) it. For example: + +```yaml title="router.yaml" +# ...other configuration... +headers: + all: # Header rules for all subgraphs + request: + - propagate: + named: 'Authorization' + rename: 'X-Authorization' +``` + +Then, update your subgraphs to check for `Authorization` or your new header name. + +### Error trying to connect: Connection reset by peer (os error 104) + +This error is likely to occur when your cloud router tries to send traffic to a port different from the listener on your AWS VPC Lattice service. Apollo GraphOS Cloud only supports communicating with private subgraphs over HTTPS on port 443. + +You can check that a Lattice service is configured to receive traffic on the right port on a service's **Routing** page: + +1. In the AWS Console for your region of choice, go to the VPC service page. +2. In the left navigation, scroll down and open **VPC Lattice > Services**. +3. Click the Lattice service used by the subgraph in question. +4. Click the **Routing** tab. + +AWS VPC Lattice routing + +5. Check that you have a listener with a `protocol:port` configuration of **HTTPS:443**. + +If not, you must create a new listener by clicking on the **Add listener** button at the top left of this section. +Refer to step 10 of [Create a Lattice service](/graphos/routing/cloud/lattice-configuration#step-2-create-a-lattice-service) for more details. + +### HTTP fetch failed from '\_subgraph\_': 403: Forbidden + +This error likely occurs for one of the following reasons: + +- One of your clients is sending a subscription request to a private subgraph over WebSockets. +- The VPC Lattice IAM policy doesn't allow traffic from Apollo GraphOS Cloud. + +#### Subscriptions over WebSockets + +Subscriptions over WebSockets aren't supported in AWS VPC Lattice, as the platform currently [lacks WebSocket support](https://docs.aws.amazon.com/vpc-lattice/latest/ug/listeners.html#listener-configuration). When sending a request to upgrade to a WebSockets connection, Lattice returns a blank response with a 403 response code. In this situation, Lattice also doesn't emit access log entries to Amazon CloudWatch Logs. [Contact your AWS account team](https://aws.amazon.com/contact-us/sales-support/) to notify them of your interest in this feature. + +#### VPC Lattice IAM policy + +You can check that a Lattice service is configured to allow traffic from Apollo GraphOS Cloud on the service's **Access** page: + +1. In the AWS Console for your region of choice, go to the VPC service page. +2. In the left navigation, scroll down and open **VPC Lattice > Services**. +3. Click the Lattice service used by the subgraph in question. +4. Click the **Access** tab. +5. Ensure that the Auth type is set to **IAM** and that the policy looks like this: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": "*", + "Action": "vpc-lattice-svcs:Invoke", + "Resource": "*", + "Condition": { + "ForAnyValue:StringLike": { + "aws:PrincipalOrgPaths": "o-9vaxczew6u/*/ou-leyb-l9pccq2t/ou-leyb-fvqz35yo/*" + } + } + } + ] +} +``` diff --git a/docs/source/routing/cloud/migrate-to-dedicated.mdx b/docs/source/routing/cloud/migrate-to-dedicated.mdx new file mode 100644 index 0000000000..96a5bddb01 --- /dev/null +++ b/docs/source/routing/cloud/migrate-to-dedicated.mdx @@ -0,0 +1,54 @@ +--- +title: Migrate to Dedicated +subtitle: Learn what to consider when migrating to a Dedicated cloud router +description: Migrate your self-hosted GraphQL APIs to a federated cloud supergraph with a pre-provisioned router on dedicated infrastructure. +--- + + + +GraphOS supports [self-hosted and cloud graphs](../../graphs/#graph-types), each recommended for different use cases. You may want to migrate to a cloud graph in these scenarios: + +- You have multiple GraphQL APIs you want to compose into a supergraph. +- You have one or more self-hosted GraphQL APIs and want to use GraphOS features beyond graph composition, for example, [`@defer` support](/graphos/routing/operations/defer) or [metrics reporting](/graphos/platform/insights/). +- You have a self-hosted supergraph and want to offload the management of your router service to Apollo while retaining or gaining access to premium router features like [subscription support](/graphos/routing/operations/subscriptions/), [authentication](/router/configuration/authn-jwt), and [more](/router/enterprise-features). Your router service may be either the GraphOS Router or the `@apollo/gateway` package. + +GraphOS offers two tiers of cloud routing: Serverless and Dedicated. This guide focuses on considerations when migrating to [Dedicated](/graphos/routing/cloud/dedicated). Refer to [this router comparison](/graphos/routing#router-comparison) to learn about the differences. + + + +Dedicated cloud routers currently support all [premium router features](/router/enterprise-features) except for [safelisting with persisted queries](/graphos/routing/security/persisted-queries/), [automatic persisted queries](/apollo-server/performance/apq/), and [offline licenses](/router/enterprise-features/#offline-enterprise-license). Support for both persisted queries features is on the roadmap. + + + +## Migrating from `@apollo/gateway` + +Cloud routers use the same [Apollo Router Core binary](https://github.com/apollographql/router) that you can self-host. Therefore, migrating from [`@apollo/gateway`](/apollo-server/using-federation/api/apollo-gateway/) entails migrating to the Apollo Router Core. Refer to the [Gateway migration guide](/graphos/reference/migration/from-gateway) for tips. + +## Router customizations + +The GraphOS Router supports a [few avenues for customization](/router/customizations/overview): + +- Custom router binaries +- Rhai scripting +- External coprocessing + +As a managed service, cloud routers don't support running custom binaries. Cloud routers don't currently support Rhai scripts, though support is on the roadmap. +Therefore, you must migrate any customizations to [external coprocessors](/graphos/routing/customization/coprocessor/) or built-in router features to use cloud routing. + +Built-in router features that you may have previously supported with customizations include: + +- [Authentication](/router/configuration/authn-jwt) +- [Telemetry and monitoring](/router/configuration/telemetry/overview) +- [Traffic shaping](/router/configuration/traffic-shaping) + +See the [router configuration documentation](/graphos/routing) for a full list of features. + +## Migration + +Once your implementation is ready to run on the router, including customizations, you can follow the [Dedicated quickstart](/graphos/routing/cloud/dedicated-quickstart) to get started. + +## Pricing considerations + +Cloud Dedicated pricing depends on throughput instead of operation volume. Refer to the [Throughput guide](/graphos/routing/cloud/throughput-guide) to learn more. + +When you no longer host your router, router-to-subgraph communication may be inter-region, inter-Availablity Zone (AZ), or egress traffic. Be aware of how your new network topology may affect your cloud costs. diff --git a/docs/source/routing/cloud/secure-subgraphs.mdx b/docs/source/routing/cloud/secure-subgraphs.mdx new file mode 100644 index 0000000000..974974ecd2 --- /dev/null +++ b/docs/source/routing/cloud/secure-subgraphs.mdx @@ -0,0 +1,89 @@ +--- +title: Secure Subgraphs +subtitle: Restrict access to your cloud supergraph using secrets +description: Generate a shared secret and configure your graph router and subgraphs to secure your federated GraphQL API. +redirectFrom: + - /graphos/graphs/securing-a-subgraph +--- + +To keep your supergraph secure, it's important that your individual subgraphs are [queried only by your router](/federation/building-supergraphs/subgraphs-overview/#securing-your-subgraphs). That's because your subgraphs expose powerful fields that the router uses to execute operations across them. External clients should not have access to these fields. + +To restrict subgraph communication to only your router, Apollo recommends creating a separate shared secret for each of your subgraphs. Whenever your router queries a subgraph, it includes that subgraph's corresponding secret in an HTTP header. + +## Secure your graph using secrets + +This article describes steps for securing your subgraphs when using a [cloud supergraph](/graphos/routing/cloud). + + + +As with all changes, we recommend first performing these steps for a non-production variant of your supergraph. + + + +### Step 1. Generate a shared secret + +You can generate a random secret using a variety of tools. For example, most password managers provide this functionality. + +Here are some shell commands that generate a suitably random secret if you have the corresponding tool installed: + +- `openssl rand -base64 256` +- `python -c "import secrets; print(secrets.token_urlsafe(256))"` +- `node -e "console.log(require('crypto').randomBytes(256).toString('base64'));"` + +### Step 2. Add the secret to your router config + +Your cloud supergraph's router needs to know the shared secret so it can include it in all requests to the corresponding subgraph. You add the secret in the **Cloud Routing** section of your graph variant's Settings page. + + + +For details, see [Managing secrets](/graphos/routing/cloud/configuration#managing-secrets). + + + +After you define the secret, you can inject its value into your router's configuration as an environment variable, as shown below. We recommend setting the value in a header named `Router-Authorization` (and again, create a separate secret for each subgraph): + +```yaml +headers: + subgraphs: + products: + request: + - insert: + name: 'Router-Authorization' + value: '${env.PRODUCTS_SUBGRAPH_SECRET}' + users: + request: + - insert: + name: 'Router-Authorization' + value: '${env.USERS_SUBGRAPH_SECRET}' +``` + +### Step 3. Configure the subgraph to require the secret + +The exact steps you take to require the shared secret in your subgraph depend on: + +- The language and framework your subgraph uses +- The service you use to host your subgraph + +Most cloud providers include a mechanism for saving secrets that are then made available to your application as environment variables. Your subgraph should read the secret from an environment variable and reject any incoming requests that don't include that secret in the specified header. + + + +All subgraph templates [provided by the Rover CLI](/graphos/graphs/creating-a-subgraph#starting-from-a-template) include this functionality out of the box. To use it, set the value of the `ROUTER_SECRET` environment variable. + +If you have an existing subgraph that wasn't created from a template, you can check a similar template's source code for an example. + + + +### Step 4. Test the configuration + +After adding the shared secret to both your router and subgraph, do the following to confirm that communication has been secured as intended: + +1. Verify that your router can still communicate with the subgraph by executing a test query against the router from the Explorer. + - Make sure the query includes at least one field from the relevant subgraph! +2. Verify that other clients can't communicate with the subgraph by executing a test query against the subgraph directly. + - This query should fail with an authorization error. + +## Next steps + +You can use router configurations such as JWT authentication, authorization, and safelisting to further secure your graph. +Check out the router configuration [security section](../../routing/security) to learn more. diff --git a/docs/source/routing/cloud/serverless.mdx b/docs/source/routing/cloud/serverless.mdx new file mode 100644 index 0000000000..027d6916f9 --- /dev/null +++ b/docs/source/routing/cloud/serverless.mdx @@ -0,0 +1,50 @@ +--- +title: Cloud Serverless Overview +subtitle: Learn about Serverless cloud routing use cases and limitations +description: Learn about Apollo GraphOS Serverless cloud routers, including intended use cases, limitations, and router statuses. +--- + + + +GraphOS Serverless cloud routers run on shared infrastructure that Apollo manages. Serverless is for demos, proof-of-concepts, and small production apps that don't need more than ten requests per second (RPS). + +## Serverless compute limitations + +The following circumstances can exhaust Serverless capacity: + +- Complex schemas can exceed available machine memory for Serverless routers. For example, Serverless routers don't support schemas with over 1,000 input types. +- Too many requests at once can overload your Serverless cloud router. It will return 429 errors to your clients. + +Because of these limitations, certain workloads might require you to upgrade to Dedicated. + +## Automatic deletion of unused routers + +When a Serverless cloud router goes 30 days without a request, Apollo deletes the router. +To avoid deletion, run a GraphQL operation on the router before the 30-day limit. + +Learn more about Serverless router statuses leading up to deletion in the next section. + +## Serverless router status + +All cloud routers can have **Initializing**, **Running**, and **Error** [statuses](../#cloud-router-status). Serverless cloud routers have these additional statuses: + +| Status | Description | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Running, will sleep soon** | Your cloud router hasn't received requests for six days and is scheduled to go to sleep soon. | +| **Sleeping** | Your cloud router hasn't received requests for seven days and is now sleeping. [Learn more.](#sleeping) | +| **Waking** | Your cloud router was asleep and recently received requests. You may experience API downtime for approximately one minute and up to five minutes. | +| **Sleeping, will delete soon** | Your cloud router has been asleep for almost 30 days and will be deleted soon. | +| **Deleted** | Your cloud router has been deleted but the associated graph variant remains. You can recreate a cloud router at anytime. [Learn more.](#deleted) | + +### Sleeping + +Serverless cloud routers go to sleep if they haven't received requests for seven days. While sleeping, your cloud router can't serve requests. + +Sleeping cloud routers automatically wake up once they receive requests. While waking, your cloud router can't process incoming requests. It typically takes about one minute to wake up. + +### Deleted + +If a cloud router has been sleeping for 30 days, Apollo automatically deletes it. +Router deletion doesn't delete the associated graph variant from GraphOS Studio, but it does spin down the infrastructure powering your cloud router. + +You can access a deleted router's [config](/graphos/reference/router/configuration) and its variant's schema, but you can't recover any [secrets that were stored in GraphOS Studio](/graphos/routing/cloud/configuration#managing-secrets). The variant's metrics are only kept for a day after deletion per the [Serverless data retention policy](https://www.apollographql.com/pricing#data-retention). diff --git a/docs/source/routing/cloud/subscriptions.mdx b/docs/source/routing/cloud/subscriptions.mdx new file mode 100644 index 0000000000..e522843b62 --- /dev/null +++ b/docs/source/routing/cloud/subscriptions.mdx @@ -0,0 +1,219 @@ +--- +title: GraphQL Subscriptions in Cloud Supergraphs +subtitle: Real-time data delivery across your services +description: Cloud routers support GraphQL subscriptions by default, enabling clients to receive real-time updates via WebSocket or HTTP callbacks. +redirectFrom: + - /graphos/operations/subscriptions +--- + + + +Cloud supergraph support for GraphQL subscriptions is currently in [preview](/graphos/reference/feature-launch-stages#preview). + +You can also use subscriptions with an Enterprise self-hosted supergraph. See the [GraphOS Router documentation](/graphos/routing/operations/subscriptions/). + + + +Cloud supergraphs provide preview support for GraphQL subscription operations: + +```graphql +subscription OnStockPricesChanged { + stockPricesChanged { + symbol + price + } +} +``` + +With a cloud supergraph, you can add `Subscription` fields to the schema of any subgraph that supports the [`graphql-transport-ws` WebSocket protocol](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md): + +```graphql title="stocks.graphql" +type Subscription { + stockPricesChanged: [Stock!]! +} +``` + +Clients can then execute subscriptions on your cloud router, which executes them on your subgraphs. + +## Prerequisites + +Before you add `Subscription` fields to your subgraphs, do all the following in the order shown to prevent errors: + +1. Make sure you've created a [cloud supergraph](/graphos/routing/cloud#cloud-supergraphs) and connected your GraphQL API to it. + +2. [Update your supergraph's build pipeline](/graphos/platform/graph-management/updates#2-update-your-build-pipeline) to use Apollo Federation 2.4 or later. + - Previous versions of Apollo Federation don't support subscription operations. +3. If your subgraph schemas specify an Apollo Federation version, modify them to use Apollo Federation 2.4 or later: + + ```graphql title="stocks.graphql" + extend schema + @link( + url: "https://specs.apollo.dev/federation/v2.4" #highlight-line + import: ["@key", "@shareable"] + ) + + type Subscription { + stockPricesChanged: [Stock!]! + } + ``` + + - You can skip modifying subgraph schemas that don't define any `Subscription` fields. + +4. In each subgraph with subscriptions, make sure the subgraph uses the [`graphql-transport-ws`](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md) WebSocket protocol for subscriptions. + +5. In each subgraph with subscriptions, make sure the subgraph hosts its subscriptions WebSocket endpoint at the path `/ws`. + + - If your WebSocket endpoint is currently hosted at a different path, you can add `/ws` as an additional path instead of removing the original path. This is helpful if legacy clients will continue executing subscriptions on your subgraph directly using the original path. + +6. Deploy your updated subgraphs. + +After you complete these prerequisites, you begin [executing subscriptions](#example-execution) on your cloud router. + +## Default configuration + +Subscriptions are enabled automatically for GraphOS Cloud with the following default router configuration: + +```yaml +subscription: + enabled: true + mode: + passthrough: + all: + path: /ws +``` + +## Example execution + +Let's say our supergraph includes the following subgraphs and partial schemas: + + + +```graphql title="Products subgraph" +type Product @key(fields: "id") { + id: ID! + name: String! + price: Int! +} + +# highlight-start +type Subscription { + productPriceChanged: Product! +} +#highlight-end +``` + +```graphql title="Reviews subgraph" +type Product @key(fields: "id") { + id: ID! + reviews: [Review!]! +} + +type Review { + score: Int! +} +``` + + + +A client can execute the following subscription against our router: + + + +Remember, clients execute subscriptions against your router [over HTTP!](#how-it-works) + +Apollo Client for [Web](/react/data/subscriptions#http), [Kotlin](/kotlin/essentials/subscriptions#configuring-http-subscriptions), and [iOS](/ios/fetching/subscriptions#http) all support HTTP-based subscriptions. + + + +```graphql +subscription OnProductPriceChanged { + productPriceChanged { + # Defined in Products subgraph + name + price + reviews { + # Defined in Reviews subgraph! + score + } + } +} +``` + +When our router receives this operation, it executes a corresponding subscription operation against the Products subgraph (over a new WebSocket connection): + +```graphql +subscription { + productPriceChanged { + id # Added for entity fetching + name + price + # Reviews fields removed! + } +} +``` + + + +- This operation adds the `Product.id` field. The router needs `@key` fields of the `Product` entity to merge entity fields from across subgraphs. +- This operation removes all fields defined in the Reviews subgraph, because the Products subgraph can't resolve them. + + + +At any point after the subscription is initiated, the Products subgraph might send updated data to our router. Whenever this happens, the router does not immediately return this data to the client, because it's missing requested fields from the Reviews subgraph! + +Instead, our router executes a standard GraphQL query against the Reviews subgraph to fetch the missing entity fields: + +```graphql +query { + _entities(representations: [...]) { + ... on Product { + reviews { + score + } + } + } +} +``` + +After receiving this query result from the Reviews subgraph, our router combines it with the data from Products and returns the combination to the subscribing client. + +## Trying subscriptions with `curl` + +To quickly try out HTTP-based subscriptions without setting up an Apollo Client library, you can execute a `curl` command against your cloud router with the following format: + +```bash title="Example curl request" showLineNumbers=false + curl 'https://main--my-org-supergraph.apollographos.net/graphql' -v \ + -H 'accept: multipart/mixed; boundary="graphql"; subscriptionSpec=1.0, application/json' \ + -H 'content-type: application/json' \ + --data-raw '{"query":"subscription OnProductPriceChanged { productPriceChanged { name price reviews { score } } }","operationName":"OnProductPriceChanged"}' +``` + +This command creates an HTTP multipart request and keeps an open connection that receives new subscription data in multiple response parts: + +```text showLineNumbers=false disableCopy=true +--graphql +content-type: application/json + +{} +--graphql +content-type: application/json + +{"payload":{"data":{"productPriceChanged":{"name":"Croissant","price":400,"reviews":[{"score":5}]}}}} +--graphql +content-type: application/json + +{"payload":{"data":{"productPriceChanged":{"name":"Croissant","price":375,"reviews":[{"score":5}]}}}} +--graphql +content-type: application/json + +{"payload":{"data":{"productPriceChanged":{"name":"Croissant","price":425,"reviews":[{"score":5}]}}}} +--graphql-- +``` + + + +This example subscription only emits three events and then directly closes the connection. + +For more information on this multipart HTTP subscription protocol, see [this article](/graphos/routing/operations/subscriptions/multipart-protocol/). + + diff --git a/docs/source/routing/cloud/throughput-guide.mdx b/docs/source/routing/cloud/throughput-guide.mdx new file mode 100644 index 0000000000..aac6471315 --- /dev/null +++ b/docs/source/routing/cloud/throughput-guide.mdx @@ -0,0 +1,157 @@ +--- +title: Throughput Guide +subtitle: Understand GCU performance and scale your graph's capacity +description: Learn about Graph Compute Units (GCUs)—a measure of throughput—and how to calculate and manage them for your supergraph on GraphOS Dedicated +--- + + + +This guide covers: + +- An overview of _Graph Compute Units_ (GCUs) and their performance expectations +- How to calculate the number of GCUs your supergraph needs +- How to manage your supergraph's throughput capacity as needs change + +## Overview + +Cloud Dedicated pricing is based on the amount of Graph Compute Units (GCUs) needed to run your graph. A GCU is a unit of throughput capacity that takes into account: + +- Processing incoming GraphQL requests +- Making a query plan across subgraphs +- Securely routing traffic to your backend services + +GCUs run on [AWS in the region of your choice](/graphos/routing/cloud/dedicated#runs-on-aws). + +### Performance expectations + + + +While Cloud Dedicated is in [preview](#private-preview), these performance expectations may change. + + + +From a single GCU, you can expect the following baseline performance: + +- 25 requests per second (RPS) +- 150 subgraph RPS +- Up to 0.5 megabytes of response data per second + +GCU performance varies depending on [additional factors](#throughput-factors), such as payload size. For example, requests that return large payloads may decrease throughput below the baseline 25 RPS. Conversely, requests that return small amounts of data may achieve above the baseline 25 RPS. + +Apollo recommends [load testing](#load-testing) your GraphQL workload on Cloud Dedicated before going into production. + +### Throughput factors + +Beyond RPS, query complexity and response size influence GCU throughput. For example, the following scenarios would decrease relative GCU throughput: + +- Requests that query more than five subgraphs +- Requests that return hundreds or thousands of fields per operation + +Requests like this decrease throughput because they require additional compute resources to execute. +Factor in additional GCUs into your [GCU calculation](#gcu-calculation) if your supergraph receives complex queries or returns large responses. + + + +GCUs include burst capacity to handle the occasional complex query. A sustained period of complex queries can [exhaust this capacity](#rate-limiting). + + + +### Rate limiting + +GCUs aren't rate-limited. However, GCUs do offer a specific amount of throughput capacity. It's possible to temporarily burst GCU throughput for a few seconds. After this period, clients receive 429 errors. Apollo recommends adding retry logic to your clients to minimize dropped requests. + +## GCU calculation + +If you already use GraphOS, you can calculate your required GCUs using the operation metrics in GraphOS Studio. + +1. In [Studio](https://studio.apollographql.com?referrer=docs-content), go to the **Insights** page and select **Last month** as the timeframe. + +GraphOS Studio Insights page with timeframe selection + +2. Scroll down to the **Request Rate** chart. This chart shows the request rate in requests per minute (RPM). +3. To calculate your required requests per second (RPS), find the peak RPM and divide it by 60. +4. Since, as [a baseline](#performance-expectations), 1 GCU can serve 25 RPS, divide your peak RPS by 25 to calculate your required GCUs. + +GraphOS Studio Insights Request Rate chart with highlighted peak + +- In the example above, the peak is **19,000 RPM**. +- `19,000 / 60 = 317`, so the graph has a peak of **317 RPS**. +- `317 / 25 = 13`, so this workload requires at least **13 GCUs** to operate. + + + +Factor in additional GCUs if your supergraph serves [complex or large requests](#throughput-factors). + + + +### Load testing + +Before going into production on Cloud Dedicated, Apollo highly recommends running a load test to simulate production traffic. +For example, suppose you run a load test of 10% of a typical day's traffic, which runs well on a single GCU. That means you need at least 10 GCUs to operate your graph on a typical day. + +## Manage capacity + +Cloud Dedicated supports mission-critical production workloads, and you can scale performance to meet the needs of your GraphQL APIs. +Dedicated supports up to 10 GCUs per GraphOS variant. + +Dedicated starts with 1 GCU per variant. You can change a variant's GCUs via either: + +- [GraphOS Studio](#edit-gcus-in-studio) +- [The Platform API](#edit-gcus-via-api) + + + +GCU updates takes about one minute to provision. + + + +### Edit GCUs in Studio + +You can change a graph variant's GCUs from the **Cloud Router** page in Studio. +Click **Manage Capacity** to the right of **Router Capacity**. + +GraphOS Studio managed GCUs + +Then, select the number of GCUs required and click **Save changes**. + +### Edit GCUs via API + +You can change a graph variant's GCUs with the following mutation from the [GraphOS Platform API](/graphos/reference/platform-api/). + +```graphql +mutation Graph($graphId: ID!, $name: String!, $gcus: Int!) { + graph(id: $graphId) { + variant(name: $name) { + router { + setGcus(gcus: $gcus) { + ... on RouterGcusSuccess { + order { + id + } + } + } + } + } + } +} +``` + +This mutation requires setting the following variables: + +- `graphId`: a graph's ID is the first part of the graph's graph ref + - You can a graph's ID in GraphOS Studio under **Settings** > **This Graph** +- `name`: the variant name + - If you haven't set a variant name, the default is `current` +- `gcus`: the number of GCUs to provision for the variant diff --git a/docs/source/routing/configure-your-router.mdx b/docs/source/routing/configure-your-router.mdx new file mode 100644 index 0000000000..c5c835b946 --- /dev/null +++ b/docs/source/routing/configure-your-router.mdx @@ -0,0 +1,103 @@ +--- +title: Configuring a Router +subtitle: Learn to configure cloud-hosted and self-hosted routers +description: Learn how to configure the Apollo GraphOS Router with environment variables, command-line options and commands, and YAML configuration files. +redirectFrom: + - /router/configuration/overview/ +--- + +You can configure a router in multiple ways. Because cloud-hosted and self-hosted routers share the common foundation of Apollo Router Core, all routers support declarative configuration with a YAML file, usually named `router.yaml`. Differences between configuring cloud-hosted and self-hosted routers: + +- A cloud-hosted router is managed by Apollo and fully integrated with GraphOS, so its configuration is provided via the GraphOS Studio IDE. +- A self-hosted router is launched via command line, so its configuration includes command-line options and environment variables. + +| | Cloud-Hosted Router | Self-Hosted Router | +| --- | :---: | :---: | +| Studio IDE | ✅ | ❌ | +| YAML file | ✅ | ✅ | +| Command-line options | ❌ | ✅ | +| Environment variables | ❌ | ✅ | + + +## YAML file-based configuration + +Both cloud-hosted and self-hosted routers support YAML file-based configuration. You can edit a YAML file named `router.yaml` to declaratively configure your router. + +- For cloud-hosted routers, use GraphOS Studio to edit `router.yaml`. +- For self-hosted routers, edit a local `router.yaml` and run your router with the `--config` flag: + + ```bash + ./router --config router.yaml + ``` + + + +For self-hosted routers, run `router config schema` to print a JSON schema of all configuration options supported by your router. + + + +To learn more about router configuration options, go to [router configuration reference docs](/graphos/reference/router/configuration). + + +## Configuring a self-hosted router + +You provide the configuration for a self-hosted router when you run a router binary or deploy a router image. + +From a command line, the router accepts configuration flags and environment variables. + +The `--config` flag sets a path to a YAML configuration file. Use this flag to customize non-default settings for your router. + + ```bash + ./router --config router.yaml + ``` + +GraphOS Routers must set the following environment variables so that they can fetch their supergraph schemas from GraphOS: + - `APOLLO_KEY` sets the graph API key to use for authenticating with GraphOS + - `APOLLO_GRAPH_REF` sets the graph ref of the graph and variant in GraphOS + +You can run your router from the command line with these environment variables: + + ```bash + APOLLO_KEY="..." APOLLO_GRAPH_REF="..." ./router + ``` + +To learn more about configuration options available to self-hosted routers, go to [router configuration reference docs](/graphos/reference/router/configuration). + +## Configuring a cloud-hosted router + +You can manage a cloud router's configuration from [GraphOS Studio](https://studio.apollographql.com?referrer=docs-content): + +- Open Studio and go to the **Cloud Router** page +- In the **General** tab, you can view: + + - The URL of your router's GraphQL API endpoint. Every cloud router URL is on a subdomain of `apollographos.net` + - Your router's status and launch history + +In the **Configuration** tab, you can manage: + + - Secrets + - Your router's YAML-base configuration + + - A router on the **Serverless** plan has the following options available: + - HTTP headers + - CORS rules + - Subgraph error inclusion + - Introspection + +## Next steps + +Browse this section to learn how to configure various features of the router: + +- **Real-Time Operations** sets up a router to support various real-time operations + +- **Security** protects a router from malicious or malformed requests and operations + +- **Performance and Scaling** optimize a router's response latency and throughput + +- **Router Customization** can add custom functionality to a router with scripts and coprocessors that can hook into a router's request-handling pipeline. + + +> Haven't run a router with GraphOS yet? Try the [quickstart](/graphos/get-started/guides/quickstart) + +> Learn more about configuration options available to cloud-hosted routers, go to [router configuration reference docs](/graphos/reference/router/configuration). + diff --git a/docs/source/customizations/coprocessor.mdx b/docs/source/routing/customization/coprocessor.mdx similarity index 95% rename from docs/source/customizations/coprocessor.mdx rename to docs/source/routing/customization/coprocessor.mdx index 9cd042c400..fd3aa8438b 100644 --- a/docs/source/customizations/coprocessor.mdx +++ b/docs/source/routing/customization/coprocessor.mdx @@ -4,7 +4,7 @@ subtitle: Customize your router's behavior in any language description: Customize the Apollo GraphOS Router with external coprocessing. Write standalone code in any language, hook into request lifecycle, and modify request/response details. --- -import CoprocTypicalConfig from '../../shared/coproc-typical-config.mdx'; +import CoprocTypicalConfig from '../../../shared/coproc-typical-config.mdx'; @@ -22,7 +22,7 @@ When your coprocessor responds to these requests, its response body can modify [ ## How it works -Whenever your router receives a client request, at various **stages** in the [request-handling lifecycle](./rhai/#router-request-lifecycle) it can send HTTP POST requests to your coprocessor: +Whenever your router receives a client request, at various **stages** in the [request-handling lifecycle](/graphos/routing/customization/rhai/#router-request-lifecycle) it can send HTTP POST requests to your coprocessor: ```mermaid flowchart TB; @@ -50,7 +50,7 @@ flowchart TB; This diagram shows request execution proceeding "down" from a client, through the router, to individual subgraphs. Execution then proceeds back "up" to the client in the reverse order. -As shown in the diagram above, the `RouterService`, `SupergraphService`, `ExecutionService`, and `SubgraphService` steps of the [request-handling lifecycle](./rhai/#router-request-lifecycle) can send these POST requests (also called **coprocessor requests**). +As shown in the diagram above, the `RouterService`, `SupergraphService`, `ExecutionService`, and `SubgraphService` steps of the [request-handling lifecycle](/graphos/routing/customization/rhai/#router-request-lifecycle) can send these POST requests (also called **coprocessor requests**). Each supported service can send its coprocessor requests at two different **stages**: @@ -68,9 +68,9 @@ If your coprocessor hooks into your router's `SubgraphService`, the router sends ## Setup -First, make sure your router is [connected to a GraphOS Enterprise organization](../enterprise-features/#enabling-enterprise-features). +First, make sure your router is [connected to a GraphOS Enterprise organization](/router/enterprise-features/#enabling-enterprise-features). -You configure external coprocessing in your router's [YAML config file](../configuration/overview/#yaml-config-file), under the `coprocessor` key. +You configure external coprocessing in your router's [YAML config file](/router/configuration/overview/#yaml-config-file), under the `coprocessor` key. ### Typical configuration @@ -94,7 +94,7 @@ In this case, the `RouterService` only sends a coprocessor request whenever it r ### Conditions -You can define [conditions](../configuration/telemetry/instrumentation/conditions) for a stage of the request lifecycle that you want to run the coprocessor. You can set coprocessor conditions with [selectors](../configuration//telemetry//instrumentation/selectors) based on headers or context entries. +You can define [conditions](/router/configuration/telemetry/instrumentation/conditions) for a stage of the request lifecycle that you want to run the coprocessor. You can set coprocessor conditions with [selectors](/router/configuration/telemetry/instrumentation/selectors) based on headers or context entries. @@ -765,7 +765,7 @@ A unique ID corresponding to the client request associated with this coprocessor -Indicates which stage of the router's [request-handling lifecycle](./rhai/#router-request-lifecycle) this coprocessor request corresponds to. +Indicates which stage of the router's [request-handling lifecycle](/graphos/routing/customization/rhai/#router-request-lifecycle) this coprocessor request corresponds to. This value is one of the following: @@ -837,7 +837,7 @@ This field's structure depends on whether the coprocessor request corresponds to - **If a standard response,** `body` usually contains `data` and/or `errors` properties for the GraphQL operation result. - **If a response "chunk",** `body` contains `data` for _some_ of the operation fields. -By default, the `RouterResponse` stage returns _redacted_ errors within the `errors` field. To process subgraph errors manually in your coprocessor, enable [subgraph error inclusion](../configuration/subgraph-error-inclusion). +By default, the `RouterResponse` stage returns _redacted_ errors within the `errors` field. To process subgraph errors manually in your coprocessor, enable [subgraph error inclusion](/router/configuration/subgraph-error-inclusion). @@ -1129,7 +1129,7 @@ If a request to a coprocessor results in a **failed response**, which is seperat ## Handling deferred query responses -GraphOS Router and Apollo Router Core support the incremental delivery of query response data via [the `@defer` directive](../executing-operations/defer-support/): +GraphOS Router and Apollo Router Core support the incremental delivery of query response data via [the `@defer` directive](/router/executing-operations/defer-support/): ```mermaid sequenceDiagram @@ -1210,7 +1210,7 @@ Subsequent response chunks omit the `headers` and `statusCode` fields: ## Adding authorization claims via coprocessor -To use the [authorization directives](../configuration/authorization#authorization-directives), a request needs to include **claims**—the details of its authentication and scope. The most straightforward way to add claims is with [JWT authentication](../configuration/./authn-jwt). You can also add claims with a [`RouterService` or `SupergraphService` coprocessor](#how-it-works) since they hook into the request lifecycle before the router applies authorization logic. +To use the [authorization directives](/router/configuration/authorization#authorization-directives), a request needs to include **claims**—the details of its authentication and scope. The most straightforward way to add claims is with [JWT authentication](/router/configuration/./authn-jwt). You can also add claims with a [`RouterService` or `SupergraphService` coprocessor](#how-it-works) since they hook into the request lifecycle before the router applies authorization logic. An example configuration of the router calling a coprocessor for authorization claims: @@ -1239,7 +1239,7 @@ This configuration prompts the router to send an HTTP POST request to your copro } ``` -When your coprocessor receives this request from the router, it should add claims to the request's [`context`](#context) and return them in the response to the router. Specifically, the coprocessor should add an entry with a claims object. The key must be `apollo_authentication::JWT::claims`, and the value should be the claims required by the authorization directives you intend to use. For example, if you want to use [`@requireScopes`](../configuration/authorization#requiresscopes), the response may look something like this: +When your coprocessor receives this request from the router, it should add claims to the request's [`context`](#context) and return them in the response to the router. Specifically, the coprocessor should add an entry with a claims object. The key must be `apollo_authentication::JWT::claims`, and the value should be the claims required by the authorization directives you intend to use. For example, if you want to use [`@requireScopes`](/router/configuration/authorization#requiresscopes), the response may look something like this: ```json { diff --git a/docs/source/customizations/custom-binary.mdx b/docs/source/routing/customization/custom-binary.mdx similarity index 96% rename from docs/source/customizations/custom-binary.mdx rename to docs/source/routing/customization/custom-binary.mdx index c2a6933146..87b87c2fae 100644 --- a/docs/source/customizations/custom-binary.mdx +++ b/docs/source/routing/customization/custom-binary.mdx @@ -4,8 +4,8 @@ subtitle: Compile a custom router binary from source description: Compile a custom Apollo Router Core binary from source. Learn to create native Rust plugins. --- -import ElasticNotice from '../../shared/elastic-notice.mdx'; -import NativePluginNotice from '../../shared/native-plugin-notice.mdx'; +import ElasticNotice from '../../../shared/elastic-notice.mdx'; +import NativePluginNotice from '../../../shared/native-plugin-notice.mdx'; Learn how to compile a custom binary from Apollo Router Core source, which is required to create custom native Rust plugins for the router. @@ -211,4 +211,4 @@ ENTRYPOINT ["/dist/router", "-s", "/dist/supergraph.graphql"] ## Related topics -* [Optimizing Custom Router Builds](/technotes/TN0030-optimizing-router-builds/) +* [Optimizing Custom Router Builds](/graphos/routing/self-hosted/containerization/optimize-build) diff --git a/docs/source/customizations/native.mdx b/docs/source/routing/customization/native-plugins.mdx similarity index 90% rename from docs/source/customizations/native.mdx rename to docs/source/routing/customization/native-plugins.mdx index 650dddcc58..aa27eb991c 100644 --- a/docs/source/customizations/native.mdx +++ b/docs/source/routing/customization/native-plugins.mdx @@ -4,10 +4,10 @@ subtitle: Extend the router with custom Rust code description: Extend the Apollo GraphOS Router or Apollo Router Core with custom Rust code. Plan, build, and register plugins. Define plugin configuration and implement lifecycle hooks. --- -import ElasticNotice from '../../shared/elastic-notice.mdx'; -import NativePluginNotice from '../../shared/native-plugin-notice.mdx'; +import ElasticNotice from '../../../shared/elastic-notice.mdx'; +import NativePluginNotice from '../../../shared/native-plugin-notice.mdx'; -Your federated graph might have specific requirements that aren't supported by the built-in [configuration options](../configuration/overview/) of the GraphOS Router or Apollo Router Core. For example, you might need to further customize the behavior of: +Your federated graph might have specific requirements that aren't supported by the built-in [configuration options](/router/configuration/overview/) of the GraphOS Router or Apollo Router Core. For example, you might need to further customize the behavior of: * Authentication/authorization * Logging @@ -23,7 +23,7 @@ In these cases, you can create custom plugins for the router. When designing a new plugin, you first want to determine which of the router's **services** the plugin should hook into to achieve its use case. -For descriptions of these services, see [Router request lifecycle](./rhai#router-request-lifecycle). +For descriptions of these services, see [Router request lifecycle](/graphos/routing/customization/rhai#router-request-lifecycle). ## Building a plugin @@ -57,7 +57,7 @@ struct Conf { } ``` -> **Note:** You need to `derive` `JsonSchema` so that your configuration can participate in [JSON schema generation](../configuration/overview/#configuration-awareness-in-your-text-editor). +> **Note:** You need to `derive` `JsonSchema` so that your configuration can participate in [JSON schema generation](/router/configuration/overview/#configuration-awareness-in-your-text-editor). Then define the plugin itself and specify the configuration as an associated type: @@ -237,7 +237,7 @@ Choose a group name that represents your organization and a name that represents ### 7. Configure your plugin -After you register your plugin, you need to add configuration for it to your [YAML configuration file](../configuration/overview/#yaml-config-file) in the `plugins:` section: +After you register your plugin, you need to add configuration for it to your [YAML configuration file](/router/configuration/overview/#yaml-config-file) in the `plugins:` section: ```yaml plugins: @@ -251,7 +251,7 @@ To create custom metrics, traces, and spans, you can use [`tracing` macros](http ### Add custom metrics -Make sure to [enable Prometheus metrics](../configuration/telemetry/exporters/metrics/prometheus) in your configuration if you want to have metrics generated by the router. +Make sure to [enable Prometheus metrics](/router/configuration/telemetry/exporters/metrics/prometheus) in your configuration if you want to have metrics generated by the router. @@ -295,7 +295,7 @@ tracing::info!( ### Add custom spans -Make sure to [enable OpenTelemetry tracing](../configuration/telemetry/exporters/tracing/overview) in your configuration if you want customize the traces generated and linked by the router. +Make sure to [enable OpenTelemetry tracing](/router/configuration/telemetry/exporters/tracing/overview) in your configuration if you want customize the traces generated and linked by the router. @@ -314,7 +314,7 @@ Like individual requests, plugins follow their own strict lifecycle that helps p ### Creation -When the router starts or reloads, it calls `new` to create instances of plugins that have configuration in the `plugins:` section of the [YAML configuration file](../configuration/overview/#yaml-config-file). If any of these calls fail, the router terminates with helpful error messages. +When the router starts or reloads, it calls `new` to create instances of plugins that have configuration in the `plugins:` section of the [YAML configuration file](/router/configuration/overview/#yaml-config-file). If any of these calls fail, the router terminates with helpful error messages. There is no sequencing for plugin registration, and registrations might even execute in parallel. A plugin should _never_ rely on the existence of _another_ plugin during initialization. @@ -322,9 +322,9 @@ There is no sequencing for plugin registration, and registrations might even exe Within a given service (router, subgraph, etc.), a _request_ is handled in the following order: -* [Rhai script](./rhai) -* [External coprocessor](./coprocessor) -* Rust plugins, in the same order they're declared in your [YAML configuration file](../configuration/overview/#yaml-config-file). +* [Rhai script](/graphos/routing/customization/rhai) +* [External coprocessor](/router/customizations/coprocessor) +* Rust plugins, in the same order they're declared in your [YAML configuration file](/router/configuration/overview/#yaml-config-file). The corresponding _response_ is handled in the opposite order. This ordering is relevant for communicating through [the `context` object](#5-define-necessary-context). diff --git a/docs/source/customizations/overview.mdx b/docs/source/routing/customization/overview.mdx similarity index 93% rename from docs/source/customizations/overview.mdx rename to docs/source/routing/customization/overview.mdx index 74a318dbc7..4eee05923e 100644 --- a/docs/source/customizations/overview.mdx +++ b/docs/source/routing/customization/overview.mdx @@ -4,21 +4,21 @@ subtitle: Extend your router with custom functionality description: Extend the GraphOS Router or Apollo Router Core with custom functionality. Understand the request lifecycle and how customizations intervene at specific points. --- -You can create **customizations** for the GraphOS Router or Apollo Router Core to add functionality that isn't available via built-in [configuration options](../configuration/overview/). For example, you can make an external call to fetch authentication data for each incoming request. +You can create **customizations** for the GraphOS Router or Apollo Router Core to add functionality that isn't available via built-in [configuration options](/router/configuration/overview/). For example, you can make an external call to fetch authentication data for each incoming request. ## Customization types The GraphOS Router supports the following customization types: -- [**Rhai scripts**](./rhai/) +- [**Rhai scripts**](/graphos/routing/customization/rhai/) - The [Rhai scripting language](https://rhai.rs/book/) lets you add functionality directly to your stock router binary by hooking into different phases of the router's request lifecycle. -- [**External co-processing**](./coprocessor/) ([Enterprise feature](../enterprise-features/)) +- [**External co-processing**](/router/customizations/coprocessor/) ([Enterprise feature](/router/enterprise-features/)) - If your organization has a [GraphOS Enterprise plan](https://www.apollographql.com/pricing/), you can write custom request-handling code in any language. This code can run in the same container as your router or separately. - The router calls your custom code via HTTP, passing it the details of each incoming client request. -The Apollo Router Core supports customization only through [Rhai scripts](./rhai/). +The Apollo Router Core supports customization only through [Rhai scripts](/graphos/routing/customization/rhai/). -Because [Rhai scripts](./rhai/) are easier to deploy, we recommend using them if they support your use case. Use external co-processing if your customization needs to do any of the following (which Rhai scripts _don't_ support): +Because [Rhai scripts](/graphos/routing/customization/rhai/) are easier to deploy, we recommend using them if they support your use case. Use external co-processing if your customization needs to do any of the following (which Rhai scripts _don't_ support): - Read or write to disk - Make network requests @@ -295,4 +295,4 @@ This guidance applies if you are: ## Customization creation -To learn how to hook in to the various lifecycle stages, including examples customizations, refer to the [Rhai scripts](./rhai/) and [external coprocessing](./coprocessor/) docs. +To learn how to hook in to the various lifecycle stages, including examples customizations, refer to the [Rhai scripts](/graphos/routing/customization/rhai/) and [external coprocessing](/router/customizations/coprocessor/) docs. diff --git a/docs/source/customizations/rhai.mdx b/docs/source/routing/customization/rhai.mdx similarity index 97% rename from docs/source/customizations/rhai.mdx rename to docs/source/routing/customization/rhai.mdx index 6bad60dfe0..0716e19639 100644 --- a/docs/source/customizations/rhai.mdx +++ b/docs/source/routing/customization/rhai.mdx @@ -24,7 +24,7 @@ Common use cases for Rhai scripts in routers include: ## Setup -To enable Rhai scripts in your router, you add the following keys to the router's [YAML config file](../configuration/overview/#yaml-config-file): +To enable Rhai scripts in your router, you add the following keys to the router's [YAML config file](/router/configuration/overview/#yaml-config-file): ```yaml title="config.yaml" # This is a top-level key. It MUST define at least one of the two @@ -39,7 +39,7 @@ rhai: main: "test.rhai" ``` -1. Add the `rhai` top-level key to your router's [YAML config file](../configuration/overview/#yaml-config-file). +1. Add the `rhai` top-level key to your router's [YAML config file](/router/configuration/overview/#yaml-config-file). * This key **must** contain at least one of a `scripts` key or a `main` key (see the example above). 2. Place all of your Rhai script files in a specific directory. * By default, the router looks in the `./rhai` directory (relative to the directory the `router` command is executed from). @@ -194,7 +194,7 @@ Each service of the router has a corresponding function that a Rhai script can d Runs at the very beginning and very end of the HTTP request lifecycle. -For example, [JWT authentication](../configuration/authn-jwt) is performed within the `RouterService`. +For example, [JWT authentication](/router/configuration/authn-jwt) is performed within the `RouterService`. Define `router_service` if your customization needs to interact with HTTP `context` and `headers`. It doesn't support access to the `body` property (see [this GitHub issue](https://github.com/apollographql/router/issues/3642) for details). @@ -286,7 +286,7 @@ Each hook in your Rhai script's [main file](#main-file) is passed a `service` ob Additionally, callbacks for `subgraph_service` can access and modify the sub-operation request that the router will send to the corresponding subgraph via `request.subgraph`. - For reference, see the fields of [`request`](./rhai-api/#request-interface). + For reference, see the fields of [`request`](/graphos/reference/router/rhai/#request-interface). * `map_response` callbacks are called in each service as execution proceeds back "to the left" from subgraphs resolving their individual sub-operations: @@ -467,7 +467,7 @@ Currently, Rhai scripts _cannot_ do the following: * Execute network requests * Read or write to disk -If your router customization needs to do any of these, you can instead use [external co-processing](./coprocessor/) (this is an [Enterprise feature](../enterprise-features)). +If your router customization needs to do any of these, you can instead use [external co-processing](/router/customizations/coprocessor/) (this is an [Enterprise feature](/router/enterprise-features)). ### Global variables @@ -545,4 +545,4 @@ Syntax highlighting can make it easier to spot errors in a script. We recommend ### Logging -For tracking down runtime errors, insert [logging](./rhai-api#logging) statements to narrow down the issue. +For tracking down runtime errors, insert [logging](/graphos/reference/router/rhai#logging) statements to narrow down the issue. diff --git a/docs/source/configuration/telemetry/apollo-telemetry.mdx b/docs/source/routing/graphos-reporting.mdx similarity index 78% rename from docs/source/configuration/telemetry/apollo-telemetry.mdx rename to docs/source/routing/graphos-reporting.mdx index c5f6c0c609..56fb8e294a 100644 --- a/docs/source/configuration/telemetry/apollo-telemetry.mdx +++ b/docs/source/routing/graphos-reporting.mdx @@ -15,14 +15,55 @@ export APOLLO_KEY= export APOLLO_GRAPH_REF=@ ``` -For more information, see [Sending operation metrics to GraphOS](/graphos/metrics/sending-operation-metrics). + + +### Usage reporting via OpenTelemetry Protocol (OTLP) + + + +Prior to router v1.49.0, all GraphOS reporting was performed using a [private tracing format](/graphos/metrics/sending-operation-metrics#reporting-format) called Apollo Usage Reporting protocol. + +As the ecosystem around OpenTelemetry (OTel) has rapidly expanded, Apollo evaluated migrating its internal tracing system to use an OTel-based protocol. + +Starting in v1.49.0, the router can use OpenTelemetry Protocol (OTLP) to report operation usage metrics to GraphOS. The benefits of reporting via OTLP include: + +- A comprehensive way to visualize the router execution path in GraphOS Studio. +- Additional spans that were previously not included in Studio traces, such as query parsing, planning, execution, and more. +- Additional metadata such as subgraph fetch details, router idle / busy timing, and more. + +#### Configuring usage reporting via OTLP + +You can enable usage reporting via OTLP by an option that can also configure the ratio of traces sent via OTLP and Apollo Usage Reporting protocol: + +- In router v1.x, this is controlled using the `experimental_otlp_tracing_sampler` option and is disabled by default. + +The supported values of the OTLP sampler option are the following: + +- `always_off`: send all traces via Apollo Usage Reporting protocol. Default for v1.x. +- `always_on`: send all traces via OTLP. Default for v2.x and later. +- `0.0 - 1.0`: the ratio of traces to send via OTLP (for example, 0.6 = 60% OTLP, 40% Apollo Usage Reporting protocol). + +The OTLP sampler is applied _after_ the common tracing sampler. In the following example, the common sampler samples traces at 1% of all traffic. The OTLP sampler sets its ratio to 0.7. This results in 0.7% of all traffic having traces sent via OTLP, and the remaining 0.3% of all traffic having traces sent via Apollo Usage Reporting protocol: + +```yaml title="router.yaml" +telemetry: + apollo: + # Send 0.7 OTLP / 0.3 Apollo + experimental_otlp_tracing_sampler: 0.7 + + exporters: + tracing: + common: + # Sample traces at 1% of all traffic + sampler: 0.01 +``` ## Reporting field-level traces In their responses to your router, your subgraphs can include [field-level traces](/federation/metrics) that indicate how long the subgraph took to resolve each field in an operation. By analyzing this data in GraphOS Studio, you can identify and optimize your slower fields: Viewing a trace in GraphOS Studio -Because field-level instrumentation is dependent on general-purpose [OpenTelemetry tracing](./exporters/tracing/overview), the value of `telemetry.apollo.field_level_instrumentation_sampler` cannot exceed the value of `telemetry.exporters.tracing.common.sampler`. +Because field-level instrumentation is dependent on general-purpose [OpenTelemetry tracing](/router/configuration/telemetry/exporters/tracing/overview), the value of `telemetry.apollo.field_level_instrumentation_sampler` cannot exceed the value of `telemetry.exporters.tracing.common.sampler`. diff --git a/docs/source/executing-operations/requests.mdx b/docs/source/routing/guides/request-format.mdx similarity index 51% rename from docs/source/executing-operations/requests.mdx rename to docs/source/routing/guides/request-format.mdx index fff8c3eadd..baf03f633b 100644 --- a/docs/source/executing-operations/requests.mdx +++ b/docs/source/routing/guides/request-format.mdx @@ -1,16 +1,18 @@ --- title: Operation Request Format -subtitle: Send requests to the router over HTTP -description: Learn how to format and send GraphQL requests to Apollo GraphOS Router or Apollo Router Core over HTTP. Explore POST and GET examples and the automatic persisted queries protocol. +subtitle: Send requests to the Apollo Router over HTTP +description: Learn how to format and send GraphQL requests to Apollo Router over HTTP. Explore POST and GET examples and the automatic persisted queries protocol. +redirectFrom: + - /router/executing-operations/requests/ --- -By default, almost every GraphQL IDE and client library takes care of sending operations in a format that the GraphOS Router or Apollo Router Core supports. This article describes that format, which is also described on [graphql.org](https://graphql.org/learn/serving-over-http/) and in [this preliminary spec](https://github.com/graphql/graphql-over-http). +By default, almost every GraphQL IDE and client library takes care of sending operations in a format that the Apollo Router supports. This article describes that format, which is also described on [graphql.org](https://graphql.org/learn/serving-over-http/) and in [this preliminary spec](https://github.com/graphql/graphql-over-http). -The router accepts queries, mutations, and subscriptions sent as POST requests. It also accepts queries sent as GET requests. +The Apollo Router accepts queries, mutations, and subscriptions sent as POST requests. It also accepts queries sent as GET requests. ## POST requests -The router accepts POST requests with a JSON body. A valid request contains a `query` field, along with optional `variables` and an `operationName` (if `query` contains multiple possible operations). +The Apollo Router accepts POST requests with a JSON body. A valid request contains a `query` field, along with optional `variables` and an `operationName` (if `query` contains multiple possible operations). Let's say we want to execute the following query: @@ -43,13 +45,18 @@ curl --request POST \ https://rover.apollo.dev/quickstart/products/graphql ``` -The router's default landing page provides a `curl` command you can use to execute a test query on your own server: +The Apollo Router's default landing page provides a `curl` command you can use to execute a test query on your own server: - +```sh +curl --request POST \ + --header 'content-type: application/json' \ + --url 'http://127.0.0.1:4000/' \ + --data '{"query":"query { __typename }"}' +``` ## GET requests -The router also accepts GET requests for queries (but not mutations). With a GET request, query details (`query`, `operationName`, `variables`) are provided as URL query parameters. The `variables` option is a URL-escaped JSON object. +The Apollo Router also accepts GET requests for queries (but not mutations). With a GET request, query details (`query`, `operationName`, `variables`) are provided as URL query parameters. The `variables` option is a URL-escaped JSON object. Here's the same query from [POST requests](#post-requests) formatted for a `curl` GET request: @@ -60,8 +67,7 @@ curl --request GET \ ## Persisted queries protocol -The Automatic Persisted Queries (APQ) feature available for Apollo Router Core and the Persisted Query List (PQL) feature available for GraphOS Router use a separate protocol to send the operation document information in the `extensions`. This protocol can also use HTTP POST or GET. See the Apollo Client docs on the [APQ protocol](/react/api/link/persisted-queries/#protocol) for details. - +The Automatic Persisted Queries (APQ) and Persisted Query List (PQL) features of the Apollo Router use a separate protocol to send the operation document information in the `extensions`. This protocol can also use HTTP POST or GET. See the Apollo Client docs on the [APQ protocol](/react/api/link/persisted-queries/#protocol) for details. ## Related topics diff --git a/docs/source/configuration/header-propagation.mdx b/docs/source/routing/header-propagation.mdx similarity index 97% rename from docs/source/configuration/header-propagation.mdx rename to docs/source/routing/header-propagation.mdx index 686f269552..5d2fae3323 100644 --- a/docs/source/configuration/header-propagation.mdx +++ b/docs/source/routing/header-propagation.mdx @@ -6,7 +6,7 @@ description: Configure which HTTP headers the Apollo GraphOS Router or Apollo Ro You can configure which HTTP headers the GraphOS Router or Apollo Route Core includes in its requests to each of your subgraphs. You can define per-subgraph header rules, along with rules that apply to _all_ subgraphs. -You define header rules in your [YAML configuration file](./overview/#yaml-config-file), like so: +You define header rules in your [YAML configuration file](/router/configuration/overview/#yaml-config-file), like so: ```yaml title="router.yaml" # ...other configuration... @@ -214,7 +214,7 @@ headers: ## Response header propagation -It is not currently possible to propagate response headers from subgraphs to clients using YAML configuration alone. However, you _can_ achieve this using [Rhai scripting](../customizations/rhai). +It is not currently possible to propagate response headers from subgraphs to clients using YAML configuration alone. However, you _can_ achieve this using [Rhai scripting](/graphos/routing/customization/rhai). This approach relies on the fact that each request has a `context` object that can store data for the duration of that request: @@ -264,7 +264,7 @@ If you require a configuration-based solution for response header propagation, [ ## Propagation between subgraphs -It is not currently possible to propagate headers between subgraphs using YAML config alone. However, you _can_ achieve this using [Rhai scripting](../customizations/rhai). +It is not currently possible to propagate headers between subgraphs using YAML config alone. However, you _can_ achieve this using [Rhai scripting](/graphos/routing/customization/rhai). This approach relies on the fact that each request has a `context` object that can store data for the duration of that request: diff --git a/docs/source/managed-federation/client-awareness.mdx b/docs/source/routing/observability/client-awareness.mdx similarity index 96% rename from docs/source/managed-federation/client-awareness.mdx rename to docs/source/routing/observability/client-awareness.mdx index d27cb1aca5..f7660f85a8 100644 --- a/docs/source/managed-federation/client-awareness.mdx +++ b/docs/source/routing/observability/client-awareness.mdx @@ -10,7 +10,7 @@ The GraphOS Router and Apollo Router Core support [client awareness](/graphos/me ## Overriding client awareness headers -Different header names can be used by updating the configuration file. If those headers will be sent by a browser, they must be allowed in the [CORS (Cross Origin Resource Sharing) configuration](../configuration/cors), as follows: +Different header names can be used by updating the configuration file. If those headers will be sent by a browser, they must be allowed in the [CORS (Cross Origin Resource Sharing) configuration](/router/configuration/cors), as follows: ```yaml title="router.yaml" telemetry: diff --git a/docs/source/routing/observability/client-id-enforcement.mdx b/docs/source/routing/observability/client-id-enforcement.mdx new file mode 100644 index 0000000000..da882d2ba7 --- /dev/null +++ b/docs/source/routing/observability/client-id-enforcement.mdx @@ -0,0 +1,143 @@ +--- +title: Client ID Enforcement +subtitle: Require client details and operation names to help monitor schema usage +description: Improve GraphQL operation monitoring by tagging operations with with client details. See code examples for Apollo GraphOS Router and Apollo Server. +published: 2022-05-31 +id: TN0001 +tags: [server, observability, router] +redirectFrom: + - /technotes/TN0001-client-id-enforcement/ +--- + +As part of GraphOS Studio metrics reporting, servers can [tag reported operations with the requesting client's name and version](/graphos/metrics/client-awareness). This helps graph maintainers understand which clients are using which fields in the schema. + +Clients can (and should) also [name their GraphQL operations](/react/data/operation-best-practices/#name-all-operations), which provides more context around how and where data is being used. + +Together, these pieces of information help teams monitor their graph and make changes to it safely. We strongly encourage that your GraphQL gateway require client details and operation names from all requesting clients. + +## Enforcing in GraphOS Router + +The GraphOS Router supports client awareness by default if the client sets the `apollographql-client-name` and `apollographql-client-id` in their requests. These values can be overridden using the [router configuration file](/router/managed-federation/client-awareness/) directly. + +Client headers can also be enforced using a [Rhai script](/graphos/routing/customization/rhai) on every incoming request. + +```rhai title="client-id.rhai" +fn supergraph_service(service) { + const request_callback = Fn("process_request"); + service.map_request(request_callback); + } + +fn process_request(request) { + log_info("processing request"); + let valid_clients = ["1", "2"]; + let valid_client_names = ["apollo-client"]; + + if ("apollographql-client-version" in request.headers && "apollographql-client-name" in request.headers) { + let client_header = request.headers["apollographql-client-version"]; + let name_header = request.headers["apollographql-client-name"]; + + if !valid_clients.contains(client_header) { + log_error("Invalid client ID provided"); + throw #{ + status: 401, + message: "Invalid client ID provided" + }; + } + if !valid_client_names.contains(name_header) { + log_error("Invalid client name provided"); + throw #{ + status: 401, + message: "Invalid client name provided" + }; + } + } + else { + log_error("No client headers set"); + throw #{ + status: 401, + message: "No client headers set" + }; + } +} +``` + + + +If you're an enterprise customer looking for more material on this topic, try the [Enterprise best practices: Router extensibility](https://www.apollographql.com/tutorials/router-extensibility) course on Odyssey. + +Not an enterprise customer? [Learn about GraphOS for Enterprise.](https://www.apollographql.com/pricing) + + + +## Enforcing in Apollo Server + +If you're using Apollo Server for your gateway, you can require client metadata in every incoming request with a [custom plugin](/apollo-server/integrations/plugins/): + + + +The header names used below are the default headers sent by Apollo Client, but you can change them to whatever names your client uses. Additionally, these changes must be reflected in the [usage reporting plugin](/apollo-server/api/plugin/usage-reporting/#generateclientinfo) to report client headers to GraphOS. For an example, see [using custom client id headers](/apollo-server/monitoring/metrics#using-custom-headers). + + + + + +```ts title="index.ts" +function clientEnforcementPlugin(): ApolloServerPlugin { + return { + async requestDidStart() { + return { + async didResolveOperation(requestContext) { + const clientName = requestContext.request.http.headers.get("apollographql-client-name"); + const clientVersion = requestContext.request.http.headers.get("apollographql-client-version"); + + if (!clientName) { + const logString = `Execution Denied: Operation has no identified client`; + requestContext.logger.debug(logString); + throw new GraphQLError(logString); + } + + if (!clientVersion) { + const logString = `Execution Denied: Client ${clientName} has no identified version`; + requestContext.logger.debug(logString); + throw new GraphQLError(logString); + } + + if (!requestContext.operationName) { + const logString = `Unnamed Operation: ${requestContext.queryHash}. All operations must be named`; + requestContext.logger.debug(logString); + + throw new GraphQLError(logString); + } + }, + }; + }, + }; +} +const server = new ApolloServer({ + typeDefs, + resolvers, + plugins: [clientEnforcementPlugin()], +}); +``` + + + +## Adding enforcement for existing clients + +If clients are already consuming your graph and are not providing client metadata, adding universal enforcement will break those clients. To resolve this you should take the following steps: + +### Use other headers + +If you have other existing headers in your HTTP requests that can be parsed to extract some client info, you can extract the info from there. + +#### GraphOS Router + +Client awareness headers should be overridden using the [router configuration file](/router/managed-federation/client-awareness/#overriding-client-awareness-headers) to use the appropriate header names. + +#### Apollo Server + +If you do change the identifying headers, also update the [Usage Reporting Plugin](/apollo-server/api/plugin/usage-reporting) to use the new headers so that the proper client info is also sent to Studio. + +### Ask clients to update their requests + +The long-term fix will require that clients start sending the required headers needed to extract client info. While clients are working on updating their requests you can add the plugin code to your gateway, but instead of throwing an error you can log a warning so that the gateway team can track when all requests have been updated. diff --git a/docs/source/routing/observability/debugging-subgraph-requests.mdx b/docs/source/routing/observability/debugging-subgraph-requests.mdx new file mode 100644 index 0000000000..4e11c45962 --- /dev/null +++ b/docs/source/routing/observability/debugging-subgraph-requests.mdx @@ -0,0 +1,88 @@ +--- +title: Debugging Subgraph Requests from the GraphOS Router or @apollo/gateway +subtitle: Log query plans and subgraph calls to help debug problematic queries +description: Log query plans and subgraph calls with the Apollo GraphOS Router and @apollo/gateway to help debug problematic queries. +published: 2023-04-13 +id: TN0039 +tags: [federation, gateway, router, subgraphs] +redirectFrom: + - /technotes/TN0039-debugging-subgraph-requests/ +--- + +As your graph grows, you may need to debug a problematic query for one reason or another. The GraphOS Router and `@apollo/gateway` both serve as an entry point into your federated graph and offer ways to debug requests. + +Each client request goes through a process called [query planning](/graphos/explorer/additional-features/#query-plans-for-supergraphs) that generates the subgraph requests to execute. You can log out the query plan in both the router and gateway. + +## Output query plans with headers + +With router v0.16.0+ and `@apollo/gateway` v2.5.4+, you can pass the following headers to return the query plans in the GraphQL response extensions: + +- Including the `Apollo-Query-Plan-Experimental` header returns the query plan in the response extensions +- Additionally, including the `Apollo-Query-Plan-Experimental-Format` header with one of the supported options changes the output format: + - A value of `prettified` returns a human-readable string of the query plan + - A value of `internal` returns a JSON representation of the query plan + +## Log router subgraph calls + +If, instead, you want to debug your subgraph HTTP requests in a router instance, you can use [Rhai scripts](/graphos/routing/customization/rhai) to log the necessary information out. An example Rhai script is shown below. + + + +While it's possible to log out the variables, Apollo strongly recommends not +doing so to avoid leaking sensitive information into your logs. + + + +```rhai +fn subgraph_service(service, subgraph) { + service.map_request(|request| { + log_info(`Subgraph: ${subgraph} Query: ${request.subgraph.body.query}`); + }); +} +``` + +The above uses an inline closure within the `map_request` function of the `subgraph_service` hook to log the subgraph-related information. + +To enable query plans, you must run the router with the `--dev` flag and leverage [Apollo Sandbox](https://studio.apollographql.com/sandbox) to [display your query plans](/graphos/explorer/additional-features/#query-plans-for-supergraphs). + +As an alternative to using `--dev`, you can also enable query plans via the below configuration option, however, Apollo strongly discourages this as the feature may be removed or renamed in the future. + +```yaml +plugins: + experimental.expose_query_plan: true +``` + +## Log `@apollo/gateway` subgraph calls + +To debug queries to your subgraphs within an `@apollo/gateway` instance, you can use a [`buildService` function](/apollo-server/using-federation/api/apollo-gateway/#configuring-the-subgraph-fetcher) to log the operation name and body. + + + +While it's possible to log out the variables, Apollo strongly recommends not +doing so to avoid leaking sensitive information into your logs. + + + +```ts +class DebugDataSource extends RemoteGraphQLDataSource { + willSendRequest({ + request + }: GraphQLDataSourceProcessOptions< + Record + >): void | Promise { + console.log(`Operation name: ${request.operationName}`); + console.log(`Query body: ${request.query}`); + } +} +const gateway = new ApolloGateway({ + debug: true, + supergraphSdl, + buildService({url}) { + return new DebugDataSource({url}); + } +}); +``` + +The above snippet creates a new class called `DebugDataSource` to log out the operation name and body using the `willSendRequest` hook, which is called before execution. + +Lastly, it also enables the `debug` setting on the gateway configuration to print out query plans in the logs for further debugging if needed. diff --git a/docs/source/routing/observability/index.mdx b/docs/source/routing/observability/index.mdx new file mode 100644 index 0000000000..48d531e69f --- /dev/null +++ b/docs/source/routing/observability/index.mdx @@ -0,0 +1,67 @@ +--- +title: Observability with GraphOS +subtitle: Capture and export signals about supergraph health with GraphOS and router telemetry +description: Learn how to collect supergraph metrics in order to monitor and optimize your GraphQL usage and performance. Collect raw metrics, insights, and alerts with Apollo GraphOS, GraphOS Studio, and GraphOS Router and Apollo Router Core. +redirectFrom: + - /federation/performance/monitoring/ +--- + +Monitoring a supergraph requires gathering metrics about each client, server, subgraph, and router involved in sending or handling requests. Ideally, the entire request pipeline—from client to router to subgraph and back—is instrumented with metrics that can be collected and exported for analysis. + +Apollo GraphOS provides the observability signals and tools your team needs to maintain the health and performance of your deployed supergraphs. Via declarative configuration, GraphOS enables routers to collect GraphQL operation and field metrics and report them back. GraphOS also specifies how to capture metrics on the clients and subgraphs handling operations. + +## Understanding runtime health with router telemetry + +Both the GraphOS Router and Apollo Router Core run a request-handling pipeline with multiple stages that starts with receiving requests and ends with sending back responses. The continuous operation and throughput of this request pipeline, or "request lifecycle," reflects the health of a running supergraph. Observability of the router request lifecycle is therefore key to understanding the health of a supergraph. + + + +To enable observability, the router supports telemetry that can be added and customized in every stage of the router request lifecycle. You can add logs, metrics, and traces, and you can export them to your application performance monitoring (APM) solution. + +To learn more, go to [Router Telemetry](/graphos/routing/observability/telemetry), then browse the pages in [Router Telemetry](/graphos/reference/router/telemetry/log-exporters/overview) reference docs. + +## Automating supergraph metrics collection with GraphOS + +Everything connected to GraphOS—including clients, routers, and subgraphs—can report metrics about GraphQL operations they send and service. GraphOS thus is the hub for collecting operation metrics, and its Studio IDE offers tools to visualize and analyze those operations and their field usage. + +The metrics that GraphOS collects can be forwarded to your APM solution. Apollo offers a [Datadog integration](/graphos/platform/insights/datadog-forwarding) to forward your graph's performance metrics to your Datadog account. + + +## Analyzing metrics and gathering insights with GraphOS + +Once the various metrics are collected by GraphOS, you can use the GraphOS Studio UI to visualize and analyze them to understand your supergraph's usage and performance. + +- Examine them in the Studio IDE from any variant's **Insights** page and use them to improve your graph's performance. + +- Create GraphOS notifications to notify your team about changes to your graph and its performance. + + + +The following require an [Enterprise plan](https://www.apollographql.com/pricing/): + +
+
+ +- Connecting a self-hosted router to GraphOS +- Forwarding metrics to Datadog + +
+ +Reporting metrics from [Apollo Server](/apollo-server) or a [monograph](/graphos/get-started/concepts/graphs/#monographs) requires an [Enterprise or legacy Team plan](https://www.apollographql.com/pricing). + +If your organization doesn't currently have an Enterprise plan, you can test out this functionality by signing up for a free [GraphOS trial](https://studio.apollographql.com/signup?referrer=docs-content). + +
+ + +## Next steps + +- Learn about metrics collection with [GraphOS Metrics Collection](/graphos/platform/insights/sending-operation-metrics). + +- Learn about subgraph observability with [Subgraph Observability](/graphos/routing/observability/subgraph-error-inclusion). + +- Learn about client observability with [Client Observability](/graphos/routing/observability/client-id-enforcement/). + +- Learn how to use insights to improve your graph's performance with [GraphOS Metrics and Insights](/graphos/platform/insights/). + +- Learn how to use notifications with [GraphOS notifications](/graphos/platform/insights/notifications). diff --git a/docs/source/routing/observability/otel-traces-to-prometheus.mdx b/docs/source/routing/observability/otel-traces-to-prometheus.mdx new file mode 100644 index 0000000000..08841ed1b0 --- /dev/null +++ b/docs/source/routing/observability/otel-traces-to-prometheus.mdx @@ -0,0 +1,106 @@ +--- +title: Connecting OpenTelemetry Traces to Prometheus +id: TN0003 +subtitle: Convert operation traces into aggregated metrics for a broader view of your graph's performance +description: Convert operation traces into aggregated metrics using OpenTelemetry Collector and Prometheus for a broader view of your graph's performance. +published: 2022-06-03 +tags: [server, observability] +redirectFrom: + - /technotes/TN0003-opentelemetry-traces-to-prometheus/ +--- + + + +Self-hosting the GraphOS Router is limited to [GraphOS Enterprise plans](https://www.apollographql.com/pricing). Other plan types use [managed cloud routing with GraphOS](/graphos/cloud-routing). Check out the [pricing page](https://www.apollographql.com/pricing#graphos-router) to learn more. + + + + + +If you're an enterprise customer looking for more material on this topic, try the [Enterprise best practices: Supergraph observability](https://www.apollographql.com/tutorials/supergraph-observability) course on Odyssey. + +Not an enterprise customer? [Learn about GraphOS for Enterprise.](https://www.apollographql.com/pricing) + + + +Operation traces provide insight into performance issues that are occurring at various execution points in your graph. However, individual traces don't provide a view of your graph's broader performance. + +Helpfully, you can convert your operation traces into aggregated metrics without requiring manual instrumentation. To accomplish this, we'll use `spanmetricsprocessor` in an OpenTelemetry Collector instance to automatically generate metrics from our existing trace spans. + +## OpenTelemetry Collector configuration + +OpenTelemetry provides two different repositories for their OpenTelemetry Collector: + +- The [core library](https://github.com/open-telemetry/opentelemetry-collector) +- The [contributor library](https://github.com/open-telemetry/opentelemetry-collector-contrib) + +These repositories are similar in scope, but the contributor library includes extended features that aren't suitable for the core library. To derive performance metrics from our existing spans, we'll use the contributor library to take advantage of the `spanmetricsprocessor` via the associated Docker image. + + + +We also recommend checking out the [Collector Builder](https://github.com/open-telemetry/opentelemetry-collector/tree/main/cmd/builder) to build binaries that are tailored to your environment instead of relying on prebuilt images. + + + +When your OpenTelemetry Collector is ready to run, you can start configuring it with this barebones example: + +```yaml +receivers: + otlp: + protocols: + grpc: + http: + cors: + allowed_origins: + - http://* + - https://* + otlp/spanmetrics: + protocols: + grpc: + endpoint: 0.0.0.0:12346 + +exporters: + prometheus: + endpoint: '0.0.0.0:9464' + +processors: + batch: + spanmetrics: + metrics_exporter: prometheus + +service: + pipelines: + traces: + receivers: [otlp] + processors: [spanmetrics, batch] + metrics: + receivers: [otlp/spanmetrics] + exporters: [prometheus] + processors: [batch] +``` + +## Apollo Server setup + +Add the OTLP Exporter (`@opentelemetry/exporter-trace-otlp-http` Node package) following the same instructions [as shown in the documentation for Apollo Server and OpenTelemetry.](/federation/opentelemetry/) + +## GraphOS Router setup + +To send traces from the GraphOS Router to OpenTelemetry Collector, see [this article](/router/configuration/telemetry/exporters/tracing/otlp). + +## Prometheus setup + +Lastly, we need to add the OpenTelemetry Collector as a target within Prometheus. It'll use the standard port for Prometheus metrics (`9464`). + +That's it- you should have access to span metrics using the same operation name! + +## Example queries + +Here are a few sample queries to help explore the data structure being reported: + +- P95 by service: `histogram_quantile(.95, sum(rate(latency_bucket[5m])) by (le, service_name))` +- Average latency by service and operation (for example `router` / `graphql.validate`): `sum by (operation, service_name)(rate(latency_sum{}[1m])) / sum by (operation, service_name)(rate(latency_count{}[1m]))` +- RPM by service: `sum(rate(calls_total{operation="HTTP POST"}[1m])) by (service_name)` + +## Full demo + +To see this in action, check out the [Supergraph Demo](https://github.com/apollographql/supergraph-demo-fed2#tracing-with-open-telemetry) repository using the OpenTelemetry-Collector-specific Docker Compose image. diff --git a/docs/source/configuration/subgraph-error-inclusion.mdx b/docs/source/routing/observability/subgraph-error-inclusion.mdx similarity index 84% rename from docs/source/configuration/subgraph-error-inclusion.mdx rename to docs/source/routing/observability/subgraph-error-inclusion.mdx index f56bcf92ba..d991a3e710 100644 --- a/docs/source/configuration/subgraph-error-inclusion.mdx +++ b/docs/source/routing/observability/subgraph-error-inclusion.mdx @@ -14,7 +14,7 @@ This redaction prevents potential leaks of sensitive information to the client. ## Configuration -To configure subgraph error inclusion, add the `include_subgraph_errors` plugin to your [YAML config file](./overview/#yaml-config-file), like so: +To configure subgraph error inclusion, add the `include_subgraph_errors` plugin to your [YAML config file](/router/configuration/overview/#yaml-config-file), like so: ```yaml title="router.yaml" include_subgraph_errors: @@ -26,8 +26,8 @@ include_subgraph_errors: Any configuration under the `subgraphs` key takes precedence over configuration under the `all` key. In the example above, subgraph errors are included from all subgraphs _except_ the `products` subgraph. ## Sending errors to GraphOS -To report the subgraph errors to GraphOS that is a separate configuration that is not affected by client subgraph error inclusion, see the [GraphOS reporting docs](./telemetry/apollo-telemetry). +To report the subgraph errors to GraphOS that is a separate configuration that is not affected by client subgraph error inclusion, see the [GraphOS reporting docs](/router/configuration/telemetry/apollo-telemetry). ## Logging GraphQL request errors -To log the GraphQL error responses (i.e. messages returned in the GraphQL `errors` array) from the router, see the [logging configuration documentation](./telemetry/exporters/logging/overview). +To log the GraphQL error responses (i.e. messages returned in the GraphQL `errors` array) from the router, see the [logging configuration documentation](/router/configuration/telemetry/exporters/logging/overview). diff --git a/docs/source/configuration/telemetry/overview.mdx b/docs/source/routing/observability/telemetry.mdx similarity index 76% rename from docs/source/configuration/telemetry/overview.mdx rename to docs/source/routing/observability/telemetry.mdx index 076630210a..fc593d8dd0 100644 --- a/docs/source/configuration/telemetry/overview.mdx +++ b/docs/source/routing/observability/telemetry.mdx @@ -6,12 +6,6 @@ description: Observe and monitor the health and performance of GraphQL operation import TelemetryPerformanceNote from '../../../shared/telemetry-performance.mdx'; - - In this overview, learn about: - How GraphOS Router and Apollo Router Core telemetry enable supergraph observability and debuggability - What data is captured in the router's logs, metrics, and traces @@ -32,7 +26,7 @@ flowchart LR ## Observability through telemetry -The health of your supergraph is only as good as the health of your router. Because the router is the single entry point to the supergraph, all client requests pass through the [router's request lifecycle](../../customizations/overview#the-request-lifecycle). Any issues with the router are likely to affect the handling of all requests to your supergraph. +The health of your supergraph is only as good as the health of your router. Because the router is the single entry point to the supergraph, all client requests pass through the [router's request lifecycle](/router/customizations/overview#the-request-lifecycle). Any issues with the router are likely to affect the handling of all requests to your supergraph. Diagnosing your router's health and performance requires it to show observable data about its inner workings. The more observable data you can monitor and analyze, the faster you can identify unhealthy behaviors, deduce root causes, and implement fixes. @@ -98,13 +92,13 @@ Logs record **events** in the router. Examples of logged events include: * Warnings about misconfiguration * Errors that occurred during a request -Logs can be consumed by [logging exporters](./exporters/logging/overview) and as part of [spans](#traces-and-spans) via [tracing exporters](./exporters/tracing/overview). +Logs can be consumed by [logging exporters](/router/configuration/telemetry/exporters/logging/overview) and as part of [spans](#traces-and-spans) via [tracing exporters](/router/configuration/telemetry/exporters/tracing/overview). ### Metrics and instruments Metrics are measurements of the router's behavior that can be exported and monitored. Different kinds of metrics include histograms, gauges, and counts. -Metrics can be consumed by _exporters_. See [Metrics exporters](./exporters/metrics/overview) for an overview of supported exporters. +Metrics can be consumed by _exporters_. See [Metrics exporters](/router/configuration/telemetry/exporters/metrics/overview) for an overview of supported exporters. An individual metric is called an _instrument_. Example instruments of the router include: @@ -112,11 +106,11 @@ An individual metric is called an _instrument_. Example instruments of the route * Histogram of request durations * Number of in-flight requests -See [Instruments](./instrumentation/instruments) for an overview of available instruments and a guide for configuring and customizing instruments. +See [Instruments](/router/configuration/telemetry/instrumentation/instruments) for an overview of available instruments and a guide for configuring and customizing instruments. ### Traces and spans -Traces monitor the flow of a request through the router. A trace is composed of [**spans**](./instrumentation/spans). A span captures a request's duration as it flows through the router request lifecycle. Spans may include contextual information about the request, such as the HTTP status code, or the name of the subgraph being queried. +Traces monitor the flow of a request through the router. A trace is composed of [**spans**](/router/configuration/telemetry/instrumentation/spans). A span captures a request's duration as it flows through the router request lifecycle. Spans may include contextual information about the request, such as the HTTP status code, or the name of the subgraph being queried. Examples of spans include: @@ -124,7 +118,7 @@ Examples of spans include: * `supergraph` - Wraps a request once GraphQL parsing has taken place * `subgraph` - Wraps a request to a subgraph. -Traces are consumed via [tracing exporters](./exporters/tracing/overview). +Traces are consumed via [tracing exporters](/router/configuration/telemetry/exporters/tracing/overview). ## Router telemetry exporters @@ -137,7 +131,7 @@ The router exports its collected telemetry in formats compatible with industry-s * Jaeger * Zipkin -For more information, see [logging exporters](./exporters/logging/overview), [metrics exporters](./exporters/metrics/overview), and [tracing exporters](./exporters/tracing/overview). +For more information, see [logging exporters](/router/configuration/telemetry/exporters/logging/overview), [metrics exporters](/router/configuration/telemetry/exporters/metrics/overview), and [tracing exporters](/router/configuration/telemetry/exporters/tracing/overview). ## Router telemetry attributes @@ -149,11 +143,11 @@ Example attributes include: * GraphQL operation name * Subgraph name -You can use [standard attributes](./instrumentation/standard-attributes) or [selectors](./instrumentation/selectors) as span attributes. +You can use [standard attributes](/router/configuration/telemetry/instrumentation/standard-attributes) or [selectors](/router/configuration/telemetry/instrumentation/selectors) as span attributes. -[Custom attributes for spans](./instrumentation/spans/#attributes) require a GraphOS [Dedicated or Enterprise plan](https://www.apollographql.com/pricing#observability). +[Custom attributes for spans](/router/configuration/telemetry/instrumentation/spans/#attributes) require a GraphOS [Dedicated or Enterprise plan](https://www.apollographql.com/pricing#observability). diff --git a/docs/source/executing-operations/defer-support.mdx b/docs/source/routing/operations/defer.mdx similarity index 69% rename from docs/source/executing-operations/defer-support.mdx rename to docs/source/routing/operations/defer.mdx index 0e6c4d76bc..7a21d412bb 100644 --- a/docs/source/executing-operations/defer-support.mdx +++ b/docs/source/routing/operations/defer.mdx @@ -35,11 +35,122 @@ To respond incrementally, the router uses a multipart-encoded HTTP response. To The router's `@defer` support is compatible with all [federation-compatible subgraph libraries](/federation/building-supergraphs/supported-subgraphs/), because the deferring logic exists entirely within the router itself. -### Basics of `@defer` +## Which fields can my router defer? -To learn the basics of the `@defer` directive and how you can use it with your supergraph, first read [Deferring query response data with GraphOS](/graphos/operations/defer). +Your router can defer the following fields in your schema: -The remainder of this article covers the router's defer implementation in greater depth. +- Root fields of the `Query` type (along with their subfields) +- Fields of any entity type (along with their subfields) + - Deferring entity fields is extremely powerful but requires some setup if you aren't using entities already. This is covered in more detail [below](#entity-fields). + +See below for more information on each of these. + +### `Query` fields + +Your router can defer any field of your schema's `Query` type, along with any subfields of those fields: + +```graphql +query GetUsersAndDeferProducts { + users { + id + } + # highlight-start + ... @defer { + products { + id + } + } + # highlight-end +} +``` + +With the query above, the router first returns a list of `User` IDs, then later completes the response with a list of `Product` IDs. + +### Entity fields + +Your router supports deferring fields of the special object types in your supergraph called entities. + +Entities are object types that often define their fields across multiple subgraphs (but they don't have to). You can identify an entity by its use of the `@key` directive. In the example subgraph schemas below, the `Product` type is an entity: + + + +```graphql title="Products subgraph" +type Product @key(fields: "id") { + id: ID! + name: String! + price: Int! +} + +type Query { + topProducts: [Product!]! +} +``` + +```graphql title="Reviews subgraph" +type Product @key(fields: "id") { + id: ID! + reviews: [Review!]! +} + +type Review { + score: Int! +} +``` + + + +Entities are query entry points into your subgraphs, and this is what enables your router to defer their fields: the router can send a followup query to a subgraph to fetch any entity fields that it doesn't fetch initially. + +Here's an example query that defers entity fields using the subgraphs above: + +```graphql +query GetProductsAndDeferReviews { + topProducts { + id + name + # highlight-start + ... @defer { + reviews { + score + } + } + # highlight-end + } +} +``` + +To handle this query, the router first resolves and returns a list of `Product` objects with their IDs and names. Later, the router completes the response by returning review scores for each of those products. + + + +It doesn't matter which subgraph defines a particular entity field! Queries can defer entity fields that are defined across any number of different subgraphs. + + + +### Defining entities in your subgraphs + +If your subgraphs don't yet include any entities, you need to define some before clients can start deferring their fields in queries. + +To learn about creating entities, see [this guide](/graphos/schema-design/federated-schemas/entities). + +## Requirements for `@defer` + +To use `@defer` successfully, your supergraph and its clients must meet the requirements listed below. These requirements are divided between [general requirements](#general-requirements) (requirements for using `@defer` at all) and [entity-specific requirements](#entity-specific-requirements) (additional requirements for using `@defer` with entity fields). + +### General requirements + +- Clients must support receiving deferred query responses as multipart HTTP responses. + - This functionality is currently supported in Apollo Client for [Web](/react/data/defer) and [Kotlin (experimental)](/kotlin/fetching/defer). +- Your supergraph must be one of: + - A [cloud supergraph](/graphos/routing/cloud#cloud-supergraphs) + - A [self-hosted supergraph](/graphos/routing/self-hosted#self-hosted-supergraphs) running the [GraphOS Router](/graphos/routing/about-router) + +### Entity-specific requirements + +- Your subgraphs must each use a [subgraph-compatible GraphQL server library](/graphos/reference/federation/compatible-subgraphs). +- You must [define one or more entities](/graphos/schema-design/federated-schemas/entities/intro#defining-an-entity) in your subgraph schemas. +- Each subgraph must define a [reference resolver](/graphos/schema-design/federated-schemas/entities/intro#2-define-a-reference-resolver) for each of its entities (or implement the corresponding functionality in your chosen subgraph library). + - This is what enables the router to directly access entity fields with followup sub-queries. ## Executing a `@defer` query @@ -56,7 +167,7 @@ Accept: multipart/mixed;deferSpec=20220824, application/json ## How does the router defer fields? -As discussed in [this article](/graphos/operations/defer/#which-fields-can-my-router-defer), the router can defer the following fields in your schema: +As discussed in [this section](#which-fields-can-my-router-defer), the router can defer the following fields in your schema: - Root fields of the `Query` type (along with their subfields) - Fields of any entity type (along with their subfields) @@ -274,7 +385,7 @@ The router supports the `@defer` directive as it's documented in [these edits to ## Disabling `@defer` -Defer support is enabled in the router by default. To _disable_ support, add `defer_support: false` to your router's [YAML config file](../configuration/overview/#yaml-config-file) under the `supergraph` key: +Defer support is enabled in the router by default. To _disable_ support, add `defer_support: false` to your router's [YAML config file](/router/configuration/overview/#yaml-config-file) under the `supergraph` key: ```yaml title="router.yaml" supergraph: diff --git a/docs/source/executing-operations/file-uploads.mdx b/docs/source/routing/operations/file-upload.mdx similarity index 99% rename from docs/source/executing-operations/file-uploads.mdx rename to docs/source/routing/operations/file-upload.mdx index 7b488fb28e..9170a22a1e 100644 --- a/docs/source/executing-operations/file-uploads.mdx +++ b/docs/source/routing/operations/file-upload.mdx @@ -286,7 +286,7 @@ Custom clients can be implemented following the [spec documentation](https://git Without additional security, HTTP multipart requests can be exploited as part of [cross-site request forgery](https://owasp.org/www-community/attacks/csrf) (CSRF) attacks. -The GraphOS Router already has a mechanism to prevent these types of attacks, which is enabled by default. You should verify that your router hasn't disabled this mechanism before using file uploads. See [Cross-Site Request Forgery Prevention](../configuration/csrf) for details. +The GraphOS Router already has a mechanism to prevent these types of attacks, which is enabled by default. You should verify that your router hasn't disabled this mechanism before using file uploads. See [Cross-Site Request Forgery Prevention](/router/configuration/csrf) for details. ## Metrics for file uploads diff --git a/docs/source/routing/operations/index.mdx b/docs/source/routing/operations/index.mdx new file mode 100644 index 0000000000..96f2310f06 --- /dev/null +++ b/docs/source/routing/operations/index.mdx @@ -0,0 +1,11 @@ +--- +title: Real-Time Operations +subtitle: Configure the router for real-time operations +description: Configure the Apollo GraphOS Router to support real-time operations, including subscriptions, defer directive, and file uploads. +--- + +Responsive applications rely on the router to handle operations in real time. You can configure to support various real-time operations: + +- [**Subscriptions**](/graphos/routing/operations/subscriptions) - support GraphQL subscription operations +- [**Defer**](/graphos/routing/operations/defer) - use the `@defer` directive to enable incremental delivery of response data +- [**File Uploads**](/graphos/routing/operations/file-upload) - upload files to the router using multipart HTTP requests diff --git a/docs/source/routing/operations/subscriptions/api-gateway.mdx b/docs/source/routing/operations/subscriptions/api-gateway.mdx new file mode 100644 index 0000000000..6c49d88679 --- /dev/null +++ b/docs/source/routing/operations/subscriptions/api-gateway.mdx @@ -0,0 +1,100 @@ +--- +title: Enabling HTTP Subscriptions with the GraphOS Router and an API Gateway +subtitle: Enable HTTP multipart subscriptions when using an API gateway in front of the router +description: Enable HTTP multipart subscriptions when using an API gateway in front of the router. +published: 2024-03-11 +id: TN0047 +tags: [router] +redirectFrom: + - /technotes/TN0047-using-http-subscriptions-api-gateway/ +--- + +Learn how to configure an API gateway to support HTTP multipart subscriptions with the GraphOS Router. + +Organizations can require their APIs—including [the router](/graphos/routing/router-api-gateway-comparison)—to be fronted by an API gateway. API gateways often aren't configured to support [subscriptions over HTTP multipart](/graphos/routing/operations/subscriptions#http-callback-setup): API gateways by default usually buffer HTTP responses, but subscriptions over HTTP multipart require multipart responses to be streamed, not buffered. + +The rest of this article describes how to configure API gateways from different vendors to stream and not buffer HTTP responses, therefore supporting subscriptions over HTTP multipart. + + + +## Azure API Management (APIM) + +By default, an HTTP API endpoint in APIM buffers each response from a downstream service, where the endpoint must receive all chunks of an HTTP response before it sends the response to the client. + +To enable HTTP subscriptions, the `forward-request` policy on the `backend` must be updated with `buffer-response="false"`. This configures the HTTP API endpoint to send the chunks of a response to the requesting client as they are received. + +```xml + + + + + +``` + + + +For more information, see the [Azure API Management policy reference - forward-request](https://learn.microsoft.com/en-us/azure/api-management/forward-request-policy#attributes). + + + + + +## Google Apigee + +By default, an HTTP API endpoint in Apigee buffers each response from a downstream service, where the endpoint must receive all chunks of an HTTP response before it sends the response to the client. + +To enable HTTP subscriptions, the `response.streaming.enabled` property must be set to `true` in both your `ProxyEndpoint` and `TargetEndpoint` definitions in the proxy bundle. This configures the HTTP API endpoint to send the chunks of a response to the requesting client as they are received. + +```xml + + + http://mocktarget.apigee.net + + true + + + +``` + +```xml + + + /v1/weather + + true + + + +``` + + + +For more information, see [Streaming requests and responses in the Apigee documentation](https://cloud.google.com/apigee/docs/api-platform/develop/enabling-streaming?hl=en). + + + +## Mulesoft + + + +### Flex Gateway + +Streaming of HTTP multipart is supported out of the box with no additional configuration required. + + + +### Proxy (Mule 4, CloudHub 2.0) + +Streaming of HTTP multipart isn't supported. Use Flex Gateway instead. + +## Kong + +Streaming of HTTP multipart is supported out of the box with no additional configuration required. + + + +## AWS API Gateway + +AWS API Gateway doesn't support streaming of HTTP data. + +A possible workaround is to use a Lambda expression which does support streaming. To learn more, see [AWS Lambda response streaming](https://aws.amazon.com/blogs/compute/introducing-aws-lambda-response-streaming/). diff --git a/docs/source/executing-operations/subscription-callback-protocol.mdx b/docs/source/routing/operations/subscriptions/callback-protocol.mdx similarity index 98% rename from docs/source/executing-operations/subscription-callback-protocol.mdx rename to docs/source/routing/operations/subscriptions/callback-protocol.mdx index 0f4c3e743c..04df169acd 100644 --- a/docs/source/executing-operations/subscription-callback-protocol.mdx +++ b/docs/source/routing/operations/subscriptions/callback-protocol.mdx @@ -8,7 +8,7 @@ This reference describes a protocol for GraphQL servers (or **subgraphs**) to se For routers with many simultaneous open subscriptions, this protocol scales better than WebSocket-based protocols, which require long-lasting open connections. -The GraphOS Router provides [support for this protocol](./subscription-support/#http-callback-setup) as part of its support for federated subscriptions: +The GraphOS Router provides [support for this protocol](/router/executing-operations/subscription-support/#http-callback-setup) as part of its support for federated subscriptions: ```mermaid sequenceDiagram diff --git a/docs/source/executing-operations/subscription-support.mdx b/docs/source/routing/operations/subscriptions/index.mdx similarity index 95% rename from docs/source/executing-operations/subscription-support.mdx rename to docs/source/routing/operations/subscriptions/index.mdx index 73bc205ea5..75cebe5e2d 100644 --- a/docs/source/executing-operations/subscription-support.mdx +++ b/docs/source/routing/operations/subscriptions/index.mdx @@ -5,15 +5,9 @@ description: Configure your router to support GraphQL subscriptions, enabling cl minVersion: 1.22.0 --- - - -**For self-hosted routers, subscription support is an [Enterprise feature](../enterprise-features/).** +**For self-hosted routers, subscription support is an [Enterprise feature](/router/enterprise-features/).** Subscription support is also available for cloud routers with a GraphOS Serverless or Dedicated plan. For cloud router subscription information, refer to [the cloud-specific docs](/graphos/operations/subscriptions). @@ -60,9 +54,9 @@ Whenever your router updates its supergraph schema at runtime, it terminates all Before you add `Subscription` fields to your subgraphs, do all of the following in the order shown to prevent schema composition errors: -1. Update your router instances to version `1.22.0` or later. [Download the latest version.](../quickstart/) +1. Update your router instances to version `1.22.0` or later. [Download the latest version.](/router/quickstart/) - Previous versions of the router don't support subscription operations. -1. Make sure your router is [connected to a GraphOS Enterprise organization](../enterprise-features/#enabling-enterprise-features). +1. Make sure your router is [connected to a GraphOS Enterprise organization](/router/enterprise-features/#enabling-enterprise-features). - Subscription support is an Enterprise feature of self-hosted routers. 1. **If you compose your router's supergraph schema with GraphOS** (instead of with the Rover CLI), [update your build pipeline](/graphos/graphs/updating#2-update-your-build-pipeline) to use Apollo Federation 2.4 or later. - Previous versions of Apollo Federation don't support subscription operations. @@ -88,7 +82,7 @@ After you complete these prerequisites, you can safely [configure your router](# ## Router setup -After completing all [prerequisites](#prerequisites), in your router's [YAML config file](../configuration/overview/#yaml-config-file), you configure how the router communicates with each of your subgraphs when executing GraphQL subscriptions. +After completing all [prerequisites](#prerequisites), in your router's [YAML config file](/router/configuration/overview/#yaml-config-file), you configure how the router communicates with each of your subgraphs when executing GraphQL subscriptions. The router supports two popular [WebSocket protocols](#websocket-setup) for subscriptions, and it also provides support for an [HTTP-callback-based protocol](#http-callback-setup). Your router must use whichever protocol is expected by each subgraph. @@ -152,7 +146,7 @@ The router provides support for receiving subgraph subscription events via HTTP - The router doesn't need to maintain a persistent connection for each distinct subscription. - You can publish events directly to the router from a pubsub system, instead of routing those events through the subgraph. -Callback mode requires your subgraph library to support the router's [HTTP callback protocol](./subscription-callback-protocol/). +Callback mode requires your subgraph library to support the router's [HTTP callback protocol](/router/executing-operations/subscription-callback-protocol/). @@ -340,7 +334,7 @@ content-type: application/json This example subscription only emits three events and then directly closes the connection. -For more information on this multipart HTTP subscription protocol, see [this article](./subscription-multipart-protocol/). +For more information on this multipart HTTP subscription protocol, see [this article](/router/executing-operations/subscription-multipart-protocol/). ## Subscription deduplication @@ -386,7 +380,7 @@ Whenever your router's supergraph schema is updated, **the router terminates all Your router's supergraph schema is updated in the following cases: - Your router regularly polls GraphOS for its supergraph schema, and an updated schema becomes available. -- Your router obtains its supergraph schema from a local file, which it watches for updates if the [`--hot-reload` option](../configuration/overview#--hr----hot-reload) is set. +- Your router obtains its supergraph schema from a local file, which it watches for updates if the [`--hot-reload` option](/router/configuration/overview#--hr----hot-reload) is set. When the router terminates subscriptions this way, it sends the following as a final response payload to all active subscribing clients: @@ -407,7 +401,7 @@ A client that receives this `SUBSCRIPTION_SCHEMA_RELOAD` error code can reconnec ### WebSocket auth support -By default, if you've configured your router to [propagate](../configuration/header-propagation/) HTTP `Authorization` headers to your subgraph, then the router automatically sets corresponding `connectionParams` when initiating a WebSocket connection to that subgraph. +By default, if you've configured your router to [propagate](/graphos/routing/header-propagation/) HTTP `Authorization` headers to your subgraph, then the router automatically sets corresponding `connectionParams` when initiating a WebSocket connection to that subgraph. For example, when your router sends the [`connection_init` message](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#connectioninit) to a subgraph, it includes the value of the `Authorization` header via the following payload: @@ -419,7 +413,7 @@ For example, when your router sends the [`connection_init` message](https://gith } ``` -To specify a custom payload for the`connection_init` message, you can write a [Rhai script](../customizations/rhai/) and use the `context` directly: +To specify a custom payload for the`connection_init` message, you can write a [Rhai script](/graphos/routing/customization/rhai/) and use the `context` directly: ```rhai fn subgraph_service(service, subgraph) { diff --git a/docs/source/executing-operations/subscription-multipart-protocol.mdx b/docs/source/routing/operations/subscriptions/multipart-protocol.mdx similarity index 98% rename from docs/source/executing-operations/subscription-multipart-protocol.mdx rename to docs/source/routing/operations/subscriptions/multipart-protocol.mdx index 6dad6feaf2..53f51ec5a2 100644 --- a/docs/source/executing-operations/subscription-multipart-protocol.mdx +++ b/docs/source/routing/operations/subscriptions/multipart-protocol.mdx @@ -4,7 +4,7 @@ subtitle: Enable clients to receive real-time updates via multipart HTTP protoco description: Enable real-time updates via multipart HTTP protocol for GraphQL subscriptions with the GraphOS Router. Learn about execution, heartbeats, and error handling. --- -To execute GraphQL subscription operations on the GraphOS Router, client apps do _not_ communicate over WebSocket. Instead, they use **HTTP with multipart responses**. This multipart protocol is built on the same [Incremental Delivery over HTTP](https://github.com/graphql/graphql-over-http/blob/main/rfcs/IncrementalDelivery.md) spec that the GraphOS Router uses to support [the `@defer` directive](./defer-support/). +To execute GraphQL subscription operations on the GraphOS Router, client apps do _not_ communicate over WebSocket. Instead, they use **HTTP with multipart responses**. This multipart protocol is built on the same [Incremental Delivery over HTTP](https://github.com/graphql/graphql-over-http/blob/main/rfcs/IncrementalDelivery.md) spec that the GraphOS Router uses to support [the `@defer` directive](/router/executing-operations/defer-support/). Use this reference if you're adding protocol support to a new GraphQL client library. [Apollo Client](/react/data/subscriptions#http), [Apollo Kotlin](/kotlin/essentials/subscriptions#configuring-http-subscriptions), and [Apollo iOS](/ios/fetching/subscriptions#http) all support this protocol. Apollo Client also provides network adapters for the [Relay](/react/data/subscriptions#relay) and [urql](/react/data/subscriptions#urql) libraries. diff --git a/docs/source/configuration/distributed-caching.mdx b/docs/source/routing/performance/caching/distributed.mdx similarity index 83% rename from docs/source/configuration/distributed-caching.mdx rename to docs/source/routing/performance/caching/distributed.mdx index fca1123ae1..2af986512b 100644 --- a/docs/source/configuration/distributed-caching.mdx +++ b/docs/source/routing/performance/caching/distributed.mdx @@ -4,24 +4,16 @@ subtitle: Configure Redis-backed caching for query plans and APQ description: Distributed caching for GraphOS Router with GraphOS Enterprise. Configure a Redis-backed cache for query plans and automatic persisted queries (APQ). --- -import RedisTLS from '../../shared/redis-tls.mdx' - - - -If you have multiple GraphOS Router instances, those instances can share a Redis-backed cache for their query plans and automatic persisted queries (APQ). This means that if _any_ of your router instances caches a particular value, _all_ of your instances can look up that value to significantly improve responsiveness. For more details on query plans and APQ, see the article on [in-memory caching](./in-memory-caching). +If you have multiple GraphOS Router instances, those instances can share a Redis-backed cache for their query plans and automatic persisted queries (APQ). This means that if _any_ of your router instances caches a particular value, _all_ of your instances can look up that value to significantly improve responsiveness. For more details on query plans and APQ, see the article on [in-memory caching](/router/configuration/in-memory-caching). ## Prerequisites To use this feature: - You must have a Redis cluster (or single instance) that your router instances can communicate with. -- You must have a [GraphOS Enterprise plan](https://www.apollographql.com/pricing/) and [connect your router to GraphOS](./overview/#environment-variables). +- You must have a [GraphOS Enterprise plan](https://www.apollographql.com/pricing/) and [connect your router to GraphOS](/router/configuration/overview/#environment-variables). ## How it works @@ -89,13 +81,13 @@ or, if configured with multiple URLs: -In your router's YAML config file, **you should specify your Redis URLs via environment variables and [variable expansion](./overview#variable-expansion)**. This prevents your Redis URLs from being committed to version control, which is especially dangerous if they include authentication information like a username and/or password. +In your router's YAML config file, **you should specify your Redis URLs via environment variables and [variable expansion](/router/configuration/overview#variable-expansion)**. This prevents your Redis URLs from being committed to version control, which is especially dangerous if they include authentication information like a username and/or password. ### Distributed query plan caching -To enable distributed caching of query plans, add the following to your router's [YAML config file](./overview/#yaml-config-file): +To enable distributed caching of query plans, add the following to your router's [YAML config file](/router/configuration/overview/#yaml-config-file): ```yaml title="router.yaml" supergraph: @@ -111,7 +103,7 @@ All query plan cache entries will be prefixed with `plan.` within the distribute ### Distributed APQ caching -To enable distributed caching of automatic persisted queries (APQ), add the following to your router's [YAML config file](./overview/#yaml-config-file): +To enable distributed caching of automatic persisted queries (APQ), add the following to your router's [YAML config file](/router/configuration/overview/#yaml-config-file): ```yaml title="router.yaml" apq: @@ -127,7 +119,7 @@ All APQ cache entries will be prefixed with `apq` followed by a null byte charac ### Common Redis configuration -Redis configuration is done in the same way for APQ caching, query plan caching and [entity caching](./entity-caching). +Redis configuration is done in the same way for APQ caching, query plan caching and [entity caching](/router/configuration/entity-caching). ```yaml title="router.yaml" supergraph: @@ -161,7 +153,23 @@ When using the same Redis instance for multiple purposes, the `namespace` option ### TLS - +For Redis TLS connections, you can set up a client certificate or override the root certificate authority by configuring `tls` in your router's [YAML config file](https://www.apollographql.com/docs/router/overview/#yaml-config-file). For example: + +```yaml +apq: + router: + cache: + redis: + urls: [ "rediss://redis.example.com:6379" ] + #highlight-start + tls: + certificate_authorities: ${file./path/to/ca.crt} + client_authentication: + certificate_chain: ${file./path/to/certificate_chain.pem} + key: ${file./path/to/key.pem} + #highlight-end +``` + ### Required to start diff --git a/docs/source/configuration/entity-caching.mdx b/docs/source/routing/performance/caching/entity.mdx similarity index 94% rename from docs/source/configuration/entity-caching.mdx rename to docs/source/routing/performance/caching/entity.mdx index 4f898ecdbc..218e6bd12a 100644 --- a/docs/source/configuration/entity-caching.mdx +++ b/docs/source/routing/performance/caching/entity.mdx @@ -5,12 +5,6 @@ description: Subgraph entity caching for GraphOS Router with GraphOS Enterprise. minVersion: 1.40.0 --- - - @@ -76,13 +70,13 @@ Follow this guide to enable and configure entity caching in the GraphOS Router. To use entity caching in the GraphOS Router, you must set up: - A Redis instance or cluster that your router instances can communicate with -- A [GraphOS Enterprise plan](https://www.apollographql.com/pricing/) that [connects your router to GraphOS](./overview/#environment-variables). +- A [GraphOS Enterprise plan](https://www.apollographql.com/pricing/) that [connects your router to GraphOS](/router/configuration/overview/#environment-variables). ### Configure router for entity caching In `router.yaml`, configure `preview_entity_cache`: - Enable entity caching globally. -- Configure Redis using the same conventions described in [distributed caching](./distributed-caching#redis-url-configuration). +- Configure Redis using the same conventions described in [distributed caching](/router/configuration/distributed-caching#redis-url-configuration). - Configure entity caching per subgraph, with overrides per subgraph for disabling entity caching and TTL. For example: @@ -375,7 +369,7 @@ The router implements the following sequence to determine whether a particular q ### Observability -The router supports a [`cache` selector](./telemetry/instrumentation/selectors#subgraph) in telemetry for the subgraph service. The selector returns the number of cache hits or misses by an entity for a subgraph request. +The router supports a [`cache` selector](/router/configuration/telemetry/instrumentation/selectors#subgraph) in telemetry for the subgraph service. The selector returns the number of cache hits or misses by an entity for a subgraph request. ## Spans @@ -451,7 +445,7 @@ If some entities were obtained from the cache, but the subgraphs that provided t ### Authorization and entity caching -When used alongside the router's [authorization directives](./authorization), cache entries are separated by authorization context. If a query contains fields that need a specific scope, the requests providing that scope have different cache entries from those not providing the scope. This means that data requiring authorization can still be safely cached and even shared across users, without needing invalidation when a user's roles change because their requests are automatically directed to a different part of the cache. +When used alongside the router's [authorization directives](/router/configuration/authorization), cache entries are separated by authorization context. If a query contains fields that need a specific scope, the requests providing that scope have different cache entries from those not providing the scope. This means that data requiring authorization can still be safely cached and even shared across users, without needing invalidation when a user's roles change because their requests are automatically directed to a different part of the cache. ### Schema updates and entity caching diff --git a/docs/source/configuration/in-memory-caching.mdx b/docs/source/routing/performance/caching/in-memory.mdx similarity index 87% rename from docs/source/configuration/in-memory-caching.mdx rename to docs/source/routing/performance/caching/in-memory.mdx index e90f6c1d3a..fbadf23a4d 100644 --- a/docs/source/configuration/in-memory-caching.mdx +++ b/docs/source/routing/performance/caching/in-memory.mdx @@ -4,12 +4,6 @@ subtitle: Configure router caching for query plans and automatic persisted queri description: Configure in-memory caching for improved performance in Apollo GraphOS Router or Apollo Router Core. Configure query plans and automatic persisted queries caching. --- - - Both GraphOS Router and Apollo Router Core use an in-memory LRU cache to store the following data: - [Generated query plans](#caching-query-plans) @@ -20,7 +14,7 @@ You can configure certain caching behaviors for generated query plans and APQ (b -If you have a GraphOS Enterprise plan, you can also configure a Redis-backed _distributed_ cache that enables multiple router instances to share cached values. For details, see [Distributed caching in the GraphOS Router](./distributed-caching/). +If you have a GraphOS Enterprise plan, you can also configure a Redis-backed _distributed_ cache that enables multiple router instances to share cached values. For details, see [Distributed caching in the GraphOS Router](/router/configuration/distributed-caching/). @@ -34,7 +28,7 @@ Whenever your router receives an incoming GraphQL operation, it generates a [que By caching previously generated query plans, your router can _skip_ generating them _again_ if a client later sends the exact same operation. This improves your router's responsiveness. -The GraphOS Router enables query plan caching by default. In your router's [YAML config file](./overview/#yaml-config-file), you can configure the maximum number of query plan entries in the cache like so: +The GraphOS Router enables query plan caching by default. In your router's [YAML config file](/router/configuration/overview/#yaml-config-file), you can configure the maximum number of query plan entries in the cache like so: ```yaml title="router.yaml" supergraph: @@ -61,7 +55,7 @@ supergraph: warmed_up_queries: 100 ``` -(In addition, the router can use the contents of the [persisted query list](./persisted-queries) to prewarm the cache. By default, it does this when loading a new schema but not on startup; you can [configure](./persisted-queries#persisted-queries#experimental_prewarm_query_plan_cache) it to change either of these defaults.) +(In addition, the router can use the contents of the [persisted query list](/router/configuration/persisted-queries) to prewarm the cache. By default, it does this when loading a new schema but not on startup; you can [configure](/router/configuration/persisted-queries#persisted-queries#experimental_prewarm_query_plan_cache) it to change either of these defaults.) To get more information on the planning and warm-up process use the following metrics (where `` can be `redis` for distributed cache or `memory`): @@ -112,7 +106,7 @@ Because the router's role differs between these two interactions, you configure ### APQ with clients -The router enables APQ caching for client operations by default. In your router's [YAML config file](./overview/#yaml-config-file), you can configure the maximum number of APQ entries in the cache like so: +The router enables APQ caching for client operations by default. In your router's [YAML config file](/router/configuration/overview/#yaml-config-file), you can configure the maximum number of APQ entries in the cache like so: ```yaml title="router.yaml" apq: @@ -133,7 +127,7 @@ apq: By default, the router does _not_ use APQ when sending queries to its subgraphs. -In your router's [YAML config file](./overview/#yaml-config-file), you can configure this APQ support with a combination of global and per-subgraph settings: +In your router's [YAML config file](/router/configuration/overview/#yaml-config-file), you can configure this APQ support with a combination of global and per-subgraph settings: ```yaml title="router.yaml" apq: diff --git a/docs/source/routing/performance/caching/index.mdx b/docs/source/routing/performance/caching/index.mdx new file mode 100644 index 0000000000..8a004e82cf --- /dev/null +++ b/docs/source/routing/performance/caching/index.mdx @@ -0,0 +1,16 @@ +--- +title: Caching +subtitle: Accelerate query retrieval with GraphOS caching. +--- + +By default, GraphOS Router stores the following data in its in-memory cache to improve performance: + +- Generated query plans +- Automatic persisted queries (APQ) +- Introspection responses + +You can configure certain caching behaviors for generated query plans and APQ (but not introspection responses). For details, see In-memory caching in the Apollo Router. + +If you have a GraphOS Enterprise plan, you can configure a Redis-backed distributed cache that enables multiple router instances to share cached values. For details, see Distributed caching in GraphOS Router. + +You can configure a Redis-backed entity cache that enables a client query to retrieve cached entity data split between subgraph responses. For details, see subgraph entity caching in GraphOS Router. diff --git a/docs/source/executing-operations/query-batching.mdx b/docs/source/routing/performance/query-batching.mdx similarity index 97% rename from docs/source/executing-operations/query-batching.mdx rename to docs/source/routing/performance/query-batching.mdx index 739f68e1d6..50530f8797 100644 --- a/docs/source/executing-operations/query-batching.mdx +++ b/docs/source/routing/performance/query-batching.mdx @@ -87,7 +87,7 @@ batching: - There are limitations on the ability of the router to preserve batches from the client request into the subgraph requests. In particular, certain forms of queries will require data to be present before they are processed. Consequently, the router will only be able to generate batches from queries which are processed which don't contain such constraints. This may result in the router issuing multiple batches or requests. -- If [query deduplication](../configuration/traffic-shaping/#query-deduplication) or [entity caching](../configuration/entity-caching) are enabled, they will not apply to batched queries. Batching will take precedence over query deduplication and entity caching. Query deduplication and Entity caching will still be performed for non-batched queries. +- If [query deduplication](/router/configuration/traffic-shaping/#query-deduplication) or [entity caching](/router/configuration/entity-caching) are enabled, they will not apply to batched queries. Batching will take precedence over query deduplication and entity caching. Query deduplication and Entity caching will still be performed for non-batched queries. diff --git a/docs/source/routing/performance/query-planner-pools.mdx b/docs/source/routing/performance/query-planner-pools.mdx new file mode 100644 index 0000000000..e278a1e030 --- /dev/null +++ b/docs/source/routing/performance/query-planner-pools.mdx @@ -0,0 +1,34 @@ +--- +title: Query Planner Pools +subtitle: Run multiple query planners in parallel +minVersion: 1.44.0 +redirectFrom: + - /router/configuration/overview/#query-planner-pools +--- + + + +You can improve the performance of the router's query planner by configuring parallelized query planning. + +By default, the query planner plans one operation at a time. It plans one operation to completion before planning the next one. This serial planning can be problematic when an operation takes a long time to plan and consequently blocks the query planner from working on other operations. + +## Configuring query planner pools + +To resolve such blocking scenarios, you can enable parallel query planning. Configure it in `router.yaml` with `supergraph.query_planning.experimental_parallelism`: + +```yaml title="router.yaml" +supergraph: + query_planning: + experimental_parallelism: auto # number of available cpus +``` + +The value of `experimental_parallelism` is the number of query planners in the router's _query planner pool_. A query planner pool is a preallocated set of query planners from which the router can use to plan operations. The total number of pools is the maximum number of query planners that can run in parallel and therefore the maximum number of operations that can be worked on simultaneously. + +Valid values of `experimental_parallelism`: +- Any integer starting from `1` +- The special value `auto`, which sets the number of query planners equal to the number of available CPUs on the router's host machine + +The default value of `experimental_parallelism` is `1`. + +In practice, you should tune `experimental_parallelism` based on metrics and benchmarks gathered from your router. \ No newline at end of file diff --git a/docs/source/configuration/traffic-shaping.mdx b/docs/source/routing/performance/traffic-shaping.mdx similarity index 96% rename from docs/source/configuration/traffic-shaping.mdx rename to docs/source/routing/performance/traffic-shaping.mdx index c6d027fbca..19cc7db838 100644 --- a/docs/source/configuration/traffic-shaping.mdx +++ b/docs/source/routing/performance/traffic-shaping.mdx @@ -8,7 +8,7 @@ The GraphOS Router and Apollo Router Core provide various features to improve th ## Configuration -By default, the `traffic_shaping` plugin is enabled with [preset values](#preset-values). To override presets, add `traffic_shaping` to your [YAML config file](./overview/#yaml-config-file) like so: +By default, the `traffic_shaping` plugin is enabled with [preset values](#preset-values). To override presets, add `traffic_shaping` to your [YAML config file](/router/configuration/overview/#yaml-config-file) like so: ```yaml title="router.yaml" traffic_shaping: @@ -86,7 +86,7 @@ traffic_shaping: -Since [deferred](../executing-operations/defer-support/#what-is-defer) fragments are separate requests, each fragment's request is individually subject to timeouts. +Since [deferred](/router/executing-operations/defer-support/#what-is-defer) fragments are separate requests, each fragment's request is individually subject to timeouts. @@ -104,7 +104,7 @@ batching: mode: batch_http_link ``` -For details, see [query batching for the router](../executing-operations/query-batching). +For details, see [query batching for the router](/router/executing-operations/query-batching). ## Subgraph traffic shaping diff --git a/docs/source/routing/query-planning/native-query-planner.mdx b/docs/source/routing/query-planning/native-query-planner.mdx new file mode 100644 index 0000000000..7da2d5a099 --- /dev/null +++ b/docs/source/routing/query-planning/native-query-planner.mdx @@ -0,0 +1,79 @@ +--- +title: Native Query Planner +subtitle: Run the Rust-native query planner in GraphOS Router +minVersion: 1.49.0 +redirectFrom: + - /router/configuration/experimental_query_planner_mode + - /router/executing-operations/native-query-planner +--- + + + +Learn to run the GraphOS Router with the Rust-native query planner and improve your query planning performance and scalability. + +## Background about query planner implementations + +In v1.49.0 the router introduced a [query planner](/graphos/routing/about-router#query-planning) implemented natively in Rust. This native query planner improves the overall performance and resource utilization of query planning. It exists alongside the legacy JavaScript implementation that uses the V8 JavaScript engine, and it will eventually replace the legacy implementation. + +### Comparing query planner implementations + +As part of the effort to ensure correctness and stability of the new query planner, starting in v1.53.0 the router enables both the new and legacy planners and runs them in parallel to compare their results by default. After their comparison, the router discards the native query planner's results and uses only the legacy planner to execute requests. The native query planner uses a single thread in the cold path of the router. It has a bounded queue of ten queries. If the queue is full, the router simply does not run the comparison to avoid excessive resource consumption. + +## Configuring query planning + +You can configure the `experimental_query_planner_mode` option in your `router.yaml` to set the query planner to run. + +The `experimental_query_planner_mode` option has the following supported modes: + +- `new`- enables only the new Rust-native query planner +- `legacy` - enables only the legacy JavaScript query planner +- `both_best_effort` (default) - enables both new and legacy query planners for comparison. The legacy query planner is used for execution. + + + +## Optimize native query planner + + + +To run the native query planner with the best performance and resource utilization, configure your router with the following options: + +```yaml title="router.yaml" +experimental_query_planner_mode: new +``` + + + +In router v1.56, running the native query planner with the best performance and resource utilization also requires setting `experimental_introspection_mode: new`. + + + +Setting `experimental_query_planner_mode: new` not only enables native query planning and schema introspection, it also disables the V8 JavaScript runtime used by the legacy query planner. Disabling V8 frees up CPU and memory and improves native query planning performance. + +Additionally, to enable more optimal native query planning and faster throughput by reducing the size of queries sent to subgraphs, you can enable query fragment generation with the following option: + +```yaml title="router.yaml" +supergraph: + generate_query_fragments: true +``` + + + +Regarding [fragment reuse and generation](/router/configuration/overview#fragment-reuse-and-generation), in the future the `generate_query_fragments` option will be the only option for handling fragments. + + + +## Metrics for native query planner + +When running both query planners for comparison with `experimental_query_planner_mode: both_best_effort`, the following metrics track mismatches and errors: + +- `apollo.router.operations.query_planner.both` with the following attributes: + - `generation.is_matched` (bool) + - `generation.js_error` (bool) + - `generation.rust_error` (bool) + +- `apollo.router.query_planning.plan.duration` with the following attributes to differentiate between planners: + - `planner` (rust | js) + +## Limitations of native query planner + +The native query planner doesn't implement `@context`. This is planned to be implemented in a future router release. diff --git a/docs/source/routing/router-api-gateway-comparison.mdx b/docs/source/routing/router-api-gateway-comparison.mdx new file mode 100644 index 0000000000..7bc41176c0 --- /dev/null +++ b/docs/source/routing/router-api-gateway-comparison.mdx @@ -0,0 +1,115 @@ +--- +title: Does GraphOS Router Replace My API Gateway? +subtitle: How the GraphOS Router differs from API gateways +description: The GraphOS Router isn't based on URLs or REST endpoints, its a GraphQL-native solution to handle your clients API operations. +published: 2023-03-31 +id: TN0037 +tags: [federation, router, gateway] +redirectFrom: + - /technotes/TN0037-api-gateways/ +--- + +The GraphOS Router is a high-performant GraphQL gateway that supports [Apollo Federation](https://www.apollographql.com/docs/federation). It handles GraphQL requests that can then be resolved by many GraphQL subgraphs underneath. When comparing the router to other API technologies in the market today, a natural first comparison to draw is to API gateways. Tools like Kong or your cloud provider offer capabilities to secure, manage, and monitor your API endpoints. +These gateways usually live at the outermost edges of your companies infrastructure. Sometimes they are even required by your security team so that all inbound and outbound traffic flows through the same top layer of your tech stack. + +The key distinction of the router is that is not based on URLs or REST endpoints. The router is a GraphQL-native solution to handle your clients API operations. + + + +Apollo GraphQL and Kong have partnered to produce a joint paper that provides API practitioners with the tools they need to navigate the complex API landscape and drive successful digital experiences. Read more in the [blog post](https://www.apollographql.com/blog/leveraging-graphql-for-next-generation-api-platforms). + + + +## GraphQL native + +First, let's define what we mean by "GraphQL native." The GraphOS Router runs all the client operations against a [supergraph](/intro/platform/). +This means that requests processed by the router are not for any random service, but are restricted to what is defined and published by the GraphQL subgraphs for a given supergraph schema. +Subgraphs define the schema and capabilities they want to expose. A well-defined GraphQL schema does not just expose all the data available in a company, instead, a [demand-oriented schema](/graphos/schema-design/guides/demand-oriented-schema-design) gives clients access to all the operations they need to execute, but without over exposing your data. +Since subgraphs are also the ones that define their service capabilities, the router can be the central location to enforce standardized rules or policies that are declared by subgraphs, for example, [a directive-based authN/Z plugin](https://www.apollographql.com/blog/platform/financial-services/directive-based-authorization-for-financial-services/). + +```graphql +type Query { + bankAccounts: [BankAccount] @authenticated @hasRole(role: ADMIN) +} +``` + +API gateways (like Apigee, Mulesoft, or ones from AWS, Azure, or Google Cloud) usually have little understanding of all the services underneath them or what their capabilities are. They may have configuration options and rules that can apply to those services, but these are blanket rules that must be configured at the gateway level, not at the service definition. +If you wanted to apply a common rule across many services it would be up to the API gateway managers to configure, deploy, and apply that new rule to a set of services rather than the individual service teams. + +```yaml +# Mock gateway rules +gatewayConfig: + myCustomRule: + tags: [requiresAuth] + ruleToApply: validate-jwt-plugin + myOtherCustomRule: + URL: '/accounts' + ruleToApply: requires-admin-permissions-plugin +``` + +## Support for non-GraphQL APIs + +GraphQL is an innovative technology that give clients much more control over their operations and a common language for service teams to communicate. However, GraphQL usually is not the one and only API technology used by companies today. +If you need to have a common gateway to secure REST endpoints and GraphQL endpoints, the GraphOS Router can be a complimentary tool that lives underneath this higher-level API gateway. You can configure company-wide policies at the outermost edge layer, and anything else that is better defined as a GraphQL-specific policy can be managed by the router. +In addition, using a [defense-in-depth](https://csrc.nist.gov/glossary/term/defense_in_depth) security strategy reduces your companies risk, so having both an API gateway and router applying shared rules can lead to a more secure environment. + +```mermaid +graph LR + +subgraph Clients + Client1 + Client2 + Client3 +end + +subgraph Partners + Partner1 + Partner2 +end + +subgraph Edge + API-Gateway +end + +style Edge height:100%; + +subgraph GraphQL + Router + Subgraph1 + Subgraph2 +end + +subgraph Data Layer + REST1 + REST2 + gRPC1 + DB1 + DB2 +end + +Client1 --> API-Gateway +Client2 --> API-Gateway +Client3 --> API-Gateway +Partner1 --> API-Gateway +Partner2 --> API-Gateway +API-Gateway --> Router +API-Gateway --> REST1 +API-Gateway --> REST2 +Router --> Subgraph1 +Router --> Subgraph2 +Subgraph1 --> gRPC1 +Subgraph1 --> DB1 +Subgraph1 --> REST2 +Subgraph2 --> DB2 +``` + +## When to consider GraphOS Router + +If you are running a GraphQL API in production, and you want to be able to: + +- [Monitor your GraphQL operations](/graphos/platform/insights/field-usage) in a way that other telemetry tools don't support while [continuing support for existing APM tools](/graphos/reference/router/telemetry/metrics-exporters/overview) +- [Safely publish new schemas without introducing a breaking change](/graphos/platform/schema-management/checks) +- [Secure your GraphQL schema](https://www.apollographql.com/docs/router/configuration/authn-jwt) +- [Extend the GraphQL runtime with custom features](https://www.apollographql.com/docs/router/customizations/overview) + +And do all this with [minimal latency and scalable performance](https://www.apollographql.com/blog/announcement/backend/apollo-router-our-graphql-federation-runtime-in-rust) then consider adopting [GraphOS and the GraphOS Router](/graphos/) today! diff --git a/docs/source/configuration/authorization.mdx b/docs/source/routing/security/authorization.mdx similarity index 88% rename from docs/source/configuration/authorization.mdx rename to docs/source/routing/security/authorization.mdx index cd241d1d4a..d59e07090f 100644 --- a/docs/source/configuration/authorization.mdx +++ b/docs/source/routing/security/authorization.mdx @@ -24,7 +24,7 @@ Services may have their own access controls, but enforcing authorization _in the clients -->|"⚠️Unauthorized
request"| router; ``` - - If every field in a particular subquery requires authorization, the router's [query planner](../customizations/overview#request-path) can _eliminate entire subgraph requests_ for unauthorized requests. For example, a request may have permission to view a particular user's posts on a social media platform but not have permission to view any of that user's personally identifiable information (PII). Check out [How it works](#how-it-works) to learn more. + - If every field in a particular subquery requires authorization, the router's [query planner](/router/customizations/overview#request-path) can _eliminate entire subgraph requests_ for unauthorized requests. For example, a request may have permission to view a particular user's posts on a social media platform but not have permission to view any of that user's personally identifiable information (PII). Check out [How it works](#how-it-works) to learn more. ```mermaid flowchart LR; @@ -38,7 +38,7 @@ Services may have their own access controls, but enforcing authorization _in the router -.->|"❌ Unauthorized
subquery"| serviceB; clients -->|"⚠️ Partially authorized
request"| router; ``` - - Also, [query deduplication](./traffic-shaping/#query-deduplication) groups requested fields based on their required authorization. Entire groups can be eliminated from the query plan if they don't have the correct authorization. + - Also, [query deduplication](/router/configuration/traffic-shaping/#query-deduplication) groups requested fields based on their required authorization. Entire groups can be eliminated from the query plan if they don't have the correct authorization. - **Declarative access rules**: You define access controls at the field level, and GraphOS [composes](#composition-and-federation) them across your services. These rules create graph-native governance without the need for an extra orchestration layer. @@ -80,7 +80,7 @@ The GraphOS Router provides access controls via **authorization directives** tha - The [`@requiresScopes`](#requiresscopes) directive allows granular access control through the scopes you define. - The [`@authenticated`](#authenticated) directive allows access to the annotated field or type for _authenticated requests only_. -- The [`@policy`](#policy) directive offloads authorization validation to a [Rhai script](../customizations/rhai/) or a [coprocessor](../customizations/coprocessor) and integrates the result in the router. It's useful when your authorization policies go beyond simple authentication and scopes. +- The [`@policy`](#policy) directive offloads authorization validation to a [Rhai script](/graphos/routing/customization/rhai/) or a [coprocessor](/router/customizations/coprocessor) and integrates the result in the router. It's useful when your authorization policies go beyond simple authentication and scopes. For example, imagine you're building a social media platform that includes a `Users` subgraph. You can use the [`@requiresScopes`](#requiresscopes) directive to declare that viewing other users' information requires the `read:user` scope: @@ -106,12 +106,12 @@ The router then enforces these directives on all incoming requests. -Only the GraphOS Router supports authorization directives—[`@apollo/gateway`](/federation/v1/gateway/) does _not_. Check out the [migration guide](../migrating-from-gateway/) if you'd like to use them. +Only the GraphOS Router supports authorization directives—[`@apollo/gateway`](/federation/v1/gateway/) does _not_. Check out the [migration guide](/router/migrating-from-gateway/) if you'd like to use them. Before using the authorization directives in your subgraph schemas, you must: -- Validate that your GraphOS Router uses version `1.29.1` or later and is [connected to your GraphOS Enterprise organization](../enterprise-features/#enabling-enterprise-features) +- Validate that your GraphOS Router uses version `1.29.1` or later and is [connected to your GraphOS Enterprise organization](/router/enterprise-features/#enabling-enterprise-features) - Include **[claims](#configure-request-claims)** in requests made to the router (for `@authenticated` and `@requiresScopes`) ### Configure request claims @@ -120,13 +120,13 @@ Claims are the individual details of a request's authentication and scope. They To provide the router with the claims it needs, you must either configure JSON Web Token (JWT) authentication or add an external coprocessor that adds claims to a request's context. In some cases (explained below), you may require both. -- **JWT authentication configuration**: If you configure [JWT authentication](./authn-jwt), the GraphOS Router [automatically adds a JWT token's claims](./authn-jwt#working-with-jwt-claims) to the request's context at the `apollo_authentication::JWT::claims` key. -- **Adding claims via coprocessor**: If you can't use JWT authentication, you can [add claims with a coprocessor](../customizations/coprocessor#adding-authorization-claims-via-coprocessor). Coprocessors let you hook into the GraphOS Router's request-handling lifecycle with custom code. -- **Augmenting JWT claims via coprocessor**: Your authorization policies may require information beyond what your JSON web tokens provide. For example, a token's claims may include user IDs, which you then use to look up user roles. For situations like this, you can [augment the claims](./authn-jwt#claim-augmentation-via-coprocessors) from your JSON web tokens with coprocessors. +- **JWT authentication configuration**: If you configure [JWT authentication](/router/configuration/authn-jwt), the GraphOS Router [automatically adds a JWT token's claims](/router/configuration/authn-jwt#working-with-jwt-claims) to the request's context at the `apollo_authentication::JWT::claims` key. +- **Adding claims via coprocessor**: If you can't use JWT authentication, you can [add claims with a coprocessor](/router/customizations/coprocessor#adding-authorization-claims-via-coprocessor). Coprocessors let you hook into the GraphOS Router's request-handling lifecycle with custom code. +- **Augmenting JWT claims via coprocessor**: Your authorization policies may require information beyond what your JSON web tokens provide. For example, a token's claims may include user IDs, which you then use to look up user roles. For situations like this, you can [augment the claims](/router/configuration/authn-jwt#claim-augmentation-via-coprocessors) from your JSON web tokens with coprocessors. ## Authorization directives -Authorization directives are turned on by default. To disable them, include the following in your router's [YAML config file](./overview/): +Authorization directives are turned on by default. To disable them, include the following in your router's [YAML config file](/router/configuration/overview/): ```yaml title="router.yaml" authorization: @@ -169,7 +169,7 @@ claims["scope"] = "scope1 scope2 scope3" -If the `apollo_authentication::JWT::claims` object holds scopes in another format, for example, an array of strings, or at a key other than `"scope"`, you can edit the claims with a [Rhai script](../customizations/rhai). +If the `apollo_authentication::JWT::claims` object holds scopes in another format, for example, an array of strings, or at a key other than `"scope"`, you can edit the claims with a [Rhai script](/graphos/routing/customization/rhai). The example below extracts an array of scopes from the `"roles"` claim and reformats them as a space-separated string. @@ -479,7 +479,7 @@ If _every_ requested field requires authentication and a request is unauthentica
-The `@policy` directive marks fields and types as restricted based on authorization policies evaluated in a [Rhai script](../customizations/rhai/) or [coprocessor](../customizations/coprocessor). This enables custom authorization validation beyond authentication and scopes. It is useful when we need more complex policy evaluation than verifying the presence of a claim value in a list (example: checking specific values in headers). +The `@policy` directive marks fields and types as restricted based on authorization policies evaluated in a [Rhai script](/graphos/routing/customization/rhai/) or [coprocessor](/router/customizations/coprocessor). This enables custom authorization validation beyond authentication and scopes. It is useful when we need more complex policy evaluation than verifying the presence of a claim value in a list (example: checking specific values in headers). @@ -493,11 +493,11 @@ The `@policy` directive includes a `policies` argument that defines an array of @policy(policies: [["roles:support"]]) ``` -Using the `@policy` directive requires a [Supergraph plugin](../customizations/overview) to evaluate the authorization policies. This is useful to bridge router authorization with an existing authorization stack or link policy execution with lookups in a database. +Using the `@policy` directive requires a [Supergraph plugin](/router/customizations/overview) to evaluate the authorization policies. This is useful to bridge router authorization with an existing authorization stack or link policy execution with lookups in a database. An overview of how `@policy` is processed through the router's request lifecycle: -* At the [`RouterService` level](../customizations/overview#the-request-lifecycle), the GraphOS Router extracts the list of policies relevant to a request from the schema and then stores them in the request's context in `apollo_authorization::policies::required` as a map `policy -> null|true|false`. +* At the [`RouterService` level](/router/customizations/overview#the-request-lifecycle), the GraphOS Router extracts the list of policies relevant to a request from the schema and then stores them in the request's context in `apollo_authorization::policies::required` as a map `policy -> null|true|false`. * At the `SupergraphService` level, you must provide a Rhai script or coprocessor to evaluate the map. If the policy is validated, the script or coprocessor should set its value to `true` or otherwise set it to `false`. If the value is left to `null`, it will be treated as `false` by the router. Afterward, the router filters the requests' types and fields to only those where the policy is `true`. @@ -522,7 +522,7 @@ scalar federation__Policy directive @policy(policies: [[federation__Policy!]!]!) on OBJECT | FIELD_DEFINITION | INTERFACE | SCALAR | ENUM ``` -Using the `@policy` directive requires a [Supergraph plugin](../customizations/overview) to evaluate the authorization policies. You can do this with a [Rhai script](../customizations/rhai/) or [coprocessor](../customizations/coprocessor). Refer to the following [example use case](#example-policy-use-case) for more information. (Although a [native plugin](../customizations/native) can also evaluate authorization policies, we don't recommend using it.) +Using the `@policy` directive requires a [Supergraph plugin](/router/customizations/overview) to evaluate the authorization policies. You can do this with a [Rhai script](/graphos/routing/customization/rhai/) or [coprocessor](/router/customizations/coprocessor). Refer to the following [example use case](#example-policy-use-case) for more information. (Although a [native plugin](/router/customizations/native) can also evaluate authorization policies, we don't recommend using it.) #### Combining policies with `AND`/`OR` logic @@ -576,7 +576,7 @@ type Post { ``` -You can use a [coprocessor](../customizations/coprocessor) called at the Supergraph request stage to receive and execute the list of policies. +You can use a [coprocessor](/router/customizations/coprocessor) called at the Supergraph request stage to receive and execute the list of policies. If you configure your router like this: @@ -892,13 +892,13 @@ The response would include an `"UNAUTHORIZED_FIELD_OR_TYPE"` error at the `/post ## Query deduplication -You can enable [query deduplication](../configuration/traffic-shaping/#query-deduplication) in the router to reduce redundant requests to a subgraph. The router does this by buffering similar queries and reusing the result. +You can enable [query deduplication](/router/configuration/traffic-shaping/#query-deduplication) in the router to reduce redundant requests to a subgraph. The router does this by buffering similar queries and reusing the result. **Query deduplication takes authorization into account.** First, the router groups unauthenticated queries together. Then it groups authenticated queries by their required scope set. It uses these groups to execute queries efficiently when fulfilling requests. ## Introspection -Introspection is turned off in the router by default, [as is best production practice](https://www.apollographql.com/blog/graphql/security/why-you-should-disable-graphql-introspection-in-production/). If you've chosen to [enable it](./overview/#introspection), keep in mind that **authorization directives don't affect introspection**. All fields that require authorization remain visible. However, directives applied to fields _aren't_ visible. If introspection might reveal too much information about internal types, then be sure it hasn't been enabled in your router configuration. +Introspection is turned off in the router by default, [as is best production practice](https://www.apollographql.com/blog/graphql/security/why-you-should-disable-graphql-introspection-in-production/). If you've chosen to [enable it](/router/configuration/overview/#introspection), keep in mind that **authorization directives don't affect introspection**. All fields that require authorization remain visible. However, directives applied to fields _aren't_ visible. If introspection might reveal too much information about internal types, then be sure it hasn't been enabled in your router configuration. With introspection turned off, you can use GraphOS's [schema registry](/graphos/delivery/) to explore your supergraph schema and empower your teammates to do the same. If you want to completely remove fields from a graph rather than just preventing access (even with introspection on), consider building a [contract graph](/graphos/delivery/contracts/). diff --git a/docs/source/configuration/cors.mdx b/docs/source/routing/security/cors.mdx similarity index 98% rename from docs/source/configuration/cors.mdx rename to docs/source/routing/security/cors.mdx index 45e331f2ba..82e4c7ccf9 100644 --- a/docs/source/configuration/cors.mdx +++ b/docs/source/routing/security/cors.mdx @@ -13,7 +13,7 @@ description: Manage browser access to your Apollo GraphOS Router or Apollo Route
-By default, the router enables _only_ GraphOS Studio to initiate browser connections to it. If your supergraph serves data to other browser-based applications, you need to do one of the following in the `cors` section of your router's [YAML config file](./overview/#yaml-config-file): +By default, the router enables _only_ GraphOS Studio to initiate browser connections to it. If your supergraph serves data to other browser-based applications, you need to do one of the following in the `cors` section of your router's [YAML config file](/router/configuration/overview/#yaml-config-file): * Add the origins of those web applications to the router's list of allowed `origins`. * Use this option if there is a known, finite list of web applications that consume your supergraph. diff --git a/docs/source/configuration/csrf.mdx b/docs/source/routing/security/csrf.mdx similarity index 95% rename from docs/source/configuration/csrf.mdx rename to docs/source/routing/security/csrf.mdx index ef1abea0b5..61fb81e79f 100644 --- a/docs/source/configuration/csrf.mdx +++ b/docs/source/routing/security/csrf.mdx @@ -5,15 +5,9 @@ description: Prevent cross-site request forgery (CSRF) attacks in the Apollo Gra minVersion: 0.9.0 --- - - ## About CSRF -[Cross-site request forgery (CSRF)](https://owasp.org/www-community/attacks/csrf) attacks use side effects of ["simple"](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests) requests to execute GraphQL operations from requests sent by sites that shouldn't be allowed to communicate with your server, based on the [CORS policy](./cors/) of your GraphOS Router or Apollo Router Core. +[Cross-site request forgery (CSRF)](https://owasp.org/www-community/attacks/csrf) attacks use side effects of ["simple"](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests) requests to execute GraphQL operations from requests sent by sites that shouldn't be allowed to communicate with your server, based on the [CORS policy](/router/configuration/cors/) of your GraphOS Router or Apollo Router Core. Your router's CORS policy enables you to control which websites can talk to your server. In most cases, the browser checks your server's CORS policy by sending a [preflight request](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request) before sending the actual operation. This is a separate HTTP request. Unlike most HTTP requests (which use the `GET` or `POST` method), this request uses a method called `OPTIONS`. The browser sends an `Origin` header, along with some other headers that start with `Access-Control-`. These headers describe the kind of request that the potentially untrusted JavaScript wants to make. Your server returns a response with `Access-Control-*` headers describing its policies (as described above), and the browser uses that response to decide whether it's OK to send the real request. Processing the `OPTIONS` preflight request never actually executes GraphQL operations. diff --git a/docs/source/executing-operations/demand-control.mdx b/docs/source/routing/security/demand-control.mdx similarity index 97% rename from docs/source/executing-operations/demand-control.mdx rename to docs/source/routing/security/demand-control.mdx index abc7983256..d4ef25212d 100644 --- a/docs/source/executing-operations/demand-control.mdx +++ b/docs/source/routing/security/demand-control.mdx @@ -5,12 +5,6 @@ description: Protect your graph from malicious or demanding clients with Apollo minVersion: 1.48.0 --- - - ## What is demand control? @@ -243,7 +237,7 @@ When enabling `demand_control` for the first time, set it to `measure` mode. Thi -New to router telemetry? See [Router Telemetry](../configuration/telemetry/overview). +New to router telemetry? See [Router Telemetry](/router/configuration/telemetry/overview). @@ -270,7 +264,7 @@ Attributes for `cost` can be applied to instruments, spans, and events—anywher | `cost.actual` | boolean | The actual cost of an operation, measured after execution. | | `cost.estimated` | boolean | The estimated cost of an operation before execution. | | `cost.delta` | boolean | The difference between the actual and estimated cost. | -| `cost.result` | boolean | The return code of the cost calculation. `COST_OK` or an [error code](../errors/#demand-control) | +| `cost.result` | boolean | The return code of the cost calculation. `COST_OK` or an [error code](/router/errors/#demand-control) | ### Selectors @@ -428,7 +422,7 @@ An example chart of a histogram: @@ -436,6 +430,6 @@ You can also chart the percentage of operations that would be allowed or rejecte diff --git a/docs/source/routing/security/index.mdx b/docs/source/routing/security/index.mdx new file mode 100644 index 0000000000..e69edf4ff5 --- /dev/null +++ b/docs/source/routing/security/index.mdx @@ -0,0 +1,21 @@ +--- +title: Supergraph Security with GraphOS Router +subtitle: Protect your supergraph at its entry point, the router +--- + +As the public endpoint of a federated GraphQL API, a GraphOS Router has the responsibility for protecting its downstream subgraphs from malicious clients and their requests. + +Its security features contribute to a defense-in-depth approach, where different authentication and authorization measures are applied in various places, from clients to the router itself to subgraphs. The supergraph can also be secured by having the router accept GraphQL operations from validated safelists of operations. + +The features covered in this section include: + +- [**Authorization**](/graphos/routing/security/authorization) - define authorized access to GraphQL fields and types by annotating schemas with authorization primitives +- [**Persisted Queries**](/graphos/routing/security/persisted-queries) - configure the router to allow clients to register and persist cached lists of safe GraphQL queries and operations +- [**Best Practices**](/graphos/platform/security/overview) - best practices for securing supergraphs +- [**CORS**](/graphos/routing/security/cors) - control router access from browser-based clients +- [**CSRF Prevention**](/graphos/routing/security/csrf) - configure cross-site request forgery (CSRF) prevention in the router +- [**Request Limits**](/graphos/routing/security/request-limits) - protect your router from requests exceeding network, parser, and operation-based limits +- [**Demand Control**](/graphos/routing/security/demand-control) - protect your graph from high-cost GraphQL operations +- [**JWT Authentication**](/graphos/routing/security/jwt) - restrict access to credentialed users and systems with JSON Web Tokens (JWT) +- [**Router Authentication**](/graphos/routing/security/router-authentication) - authorization and authentication strategies to secure your graph +- [**Subgraph Authentication**](/graphos/routing/security/subgraph-authentication) - implement subgraph authentication by using AWS SigV4 \ No newline at end of file diff --git a/docs/source/configuration/authn-jwt.mdx b/docs/source/routing/security/jwt.mdx similarity index 88% rename from docs/source/configuration/authn-jwt.mdx rename to docs/source/routing/security/jwt.mdx index bb16070e10..4083721245 100644 --- a/docs/source/configuration/authn-jwt.mdx +++ b/docs/source/routing/security/jwt.mdx @@ -4,17 +4,11 @@ subtitle: Restrict access to credentialed users and systems description: Protect sensitive data by enabling JWT authentication in the Apollo GraphOS Router. Restrict access to credentialed users and systems. --- - - Authentication is crucial to prevent illegitimate access and protect sensitive data in your graph. The GraphOS Router supports request authentication and key rotation via the [JSON Web Token](https://www.rfc-editor.org/rfc/rfc7519) (**JWT**) and [JSON Web Key](https://www.rfc-editor.org/rfc/rfc7517) (**JWK**) standards. This support is compatible with popular identity providers (**IdPs**) like Okta and Auth0. -By enabling JWT authentication, you can block malicious traffic at the _edge_ of your graph instead of relying on [header forwarding](./header-propagation/) to propagate tokens to your subgraphs. +By enabling JWT authentication, you can block malicious traffic at the _edge_ of your graph instead of relying on [header forwarding](/graphos/routing/header-propagation/) to propagate tokens to your subgraphs. @@ -35,7 +29,7 @@ These are the high-level steps of JWT-based authentication with the GraphOS Rout - Your router obtains all of its known JWKs from URLs that you specify in its configuration file. Each URL provides its keys within a single JSON object called a [JWK Set](https://www.rfc-editor.org/rfc/rfc7517#section-5) (or a **JWKS**). - **If validation fails, the router rejects the request.** This can occur if the JWT is malformed, or if it's been expired for more than 60 seconds (this window accounts for synchronization issues). -5. The router extracts all **claims** from the validated JWT and includes them in the request's context, making them available to your [router customizations](../customizations/overview/), such as Rhai scripts. +5. The router extracts all **claims** from the validated JWT and includes them in the request's context, making them available to your [router customizations](/router/customizations/overview/), such as Rhai scripts. 6. Your customizations can handle the request differently depending on the details of the extracted claims, and/or you can propagate the claims to subgraphs to enable more granular access control. - For examples, [see below](#working-with-jwt-claims). @@ -45,7 +39,7 @@ If you use your own custom IdP, [advanced configuration is required](#creating-y Otherwise, if you issue JWTs via a popular third-party IdP (Auth0, Okta, PingOne, etc.), enabling JWT authentication in your router is a two step process described below. -1. Set configuration options for JWT authentication in your router's [YAML config file](./overview/#yaml-config-file), under the `authentication` key: +1. Set configuration options for JWT authentication in your router's [YAML config file](/router/configuration/overview/#yaml-config-file), under the `authentication` key: ```yaml title="router.yaml" authentication: @@ -221,17 +215,17 @@ authorization: **Claims** are the individual details of a JWT's scope. They might include details like the ID of the associated user, any roles assigned to that user, and the JWT's expiration time. [See the spec.](https://www.rfc-editor.org/rfc/rfc7519#section-4) -Because claims are added to the context, you can define custom logic for handling each request based on the details of its claims. You can define this logic within a Rhai script or external coprocessor at the supergraph service level (for more on these options, see [Router Customizations](../customizations/overview/)). +Because claims are added to the context, you can define custom logic for handling each request based on the details of its claims. You can define this logic within a Rhai script or external coprocessor at the supergraph service level (for more on these options, see [Router Customizations](/router/customizations/overview/)). -Below are 2 example [Rhai script](../customizations/rhai/) customizations that demonstrate actions the router can perform based on a request's claims. +Below are 2 example [Rhai script](/graphos/routing/customization/rhai/) customizations that demonstrate actions the router can perform based on a request's claims. ### Example: Forwarding claims to subgraphs as headers -Below is an example [Rhai script](../customizations/rhai/) that forwards a JWT's claims to individual subgraphs via HTTP headers (one header for each claim). This enables each subgraph to define logic to handle (or potentially reject) incoming requests based on claim details. This function should be imported and run in your [`main.rhai`](#example-mainrhai) file. +Below is an example [Rhai script](/graphos/routing/customization/rhai/) that forwards a JWT's claims to individual subgraphs via HTTP headers (one header for each claim). This enables each subgraph to define logic to handle (or potentially reject) incoming requests based on claim details. This function should be imported and run in your [`main.rhai`](#example-mainrhai) file. -This script should be run in the router's `SubgraphService`, which executes before the router sends a subquery to an individual subgraph. [Learn more about router services.](../customizations/rhai#router-request-lifecycle) +This script should be run in the router's `SubgraphService`, which executes before the router sends a subquery to an individual subgraph. [Learn more about router services.](/graphos/routing/customization/rhai#router-request-lifecycle) @@ -260,17 +254,17 @@ fn process_request(request) { -Explicitly listing claims and _always_ setting headers for them is strongly recommended to avoid possible security issues when [forwarding headers](./header-propagation/) to subgraphs. +Explicitly listing claims and _always_ setting headers for them is strongly recommended to avoid possible security issues when [forwarding headers](/graphos/routing/header-propagation/) to subgraphs. ### Example: Forwarding claims to subgraphs as GraphQL extensions -Below is an example [Rhai script](../customizations/rhai/) that forwards a JWT's claims to individual subgraphs via GraphQL extension. This enables each subgraph to define logic to handle (or potentially reject) incoming requests based on claim details. This function should be imported and run in your [`main.rhai`](#example-mainrhai) file. +Below is an example [Rhai script](/graphos/routing/customization/rhai/) that forwards a JWT's claims to individual subgraphs via GraphQL extension. This enables each subgraph to define logic to handle (or potentially reject) incoming requests based on claim details. This function should be imported and run in your [`main.rhai`](#example-mainrhai) file. -This script should be run in the router's `SubgraphService`, which executes before the router sends a subquery to an individual subgraph. [Learn more about router services.](../customizations/rhai#router-request-lifecycle) +This script should be run in the router's `SubgraphService`, which executes before the router sends a subquery to an individual subgraph. [Learn more about router services.](/graphos/routing/customization/rhai#router-request-lifecycle) @@ -292,11 +286,11 @@ fn process_request(request) { ### Example: Throwing errors for invalid claims -Below is an example [Rhai script](../customizations/rhai/) that throws distinct errors for different invalid JWT claim details. This function should be imported and run in your [`main.rhai`](#example-mainrhai) file. +Below is an example [Rhai script](/graphos/routing/customization/rhai/) that throws distinct errors for different invalid JWT claim details. This function should be imported and run in your [`main.rhai`](#example-mainrhai) file. -This script should be run in the router's `SupergraphService`, which executes before the router begins generating the query plan for an operation. [Learn more about router services.](../customizations/rhai#router-request-lifecycle) +This script should be run in the router's `SupergraphService`, which executes before the router begins generating the query plan for an operation. [Learn more about router services.](/graphos/routing/customization/rhai#router-request-lifecycle) @@ -321,7 +315,7 @@ fn process_request(request) { ### Example `main.rhai` -In order to use the above Rhai examples, you must import them into your [`main.rhai`](../customizations/rhai#the-main-file) like this: +In order to use the above Rhai examples, you must import them into your [`main.rhai`](/graphos/routing/customization/rhai#the-main-file) like this: @@ -350,18 +344,18 @@ fn subgraph_service(service, subgraph) { ### Claim augmentation via coprocessors -You may require information beyond what your JSON web tokens provide. For example, a token's claims may include user IDs, which you then use to look up user roles. For situations like this, you can augment the claims from your JSON web tokens with [coprocessors](../customizations/coprocessor#how-it-works). +You may require information beyond what your JSON web tokens provide. For example, a token's claims may include user IDs, which you then use to look up user roles. For situations like this, you can augment the claims from your JSON web tokens with [coprocessors](/router/customizations/coprocessor#how-it-works). -A [`RouterService` coprocessor](../customizations/coprocessor#how-it-works) is appropriate for augmenting claims since the router calls it directly after receiving a client request. The router calls it after the JWT authentication plugin, so you can use a `RouterService` coprocessor to: +A [`RouterService` coprocessor](/router/customizations/coprocessor#how-it-works) is appropriate for augmenting claims since the router calls it directly after receiving a client request. The router calls it after the JWT authentication plugin, so you can use a `RouterService` coprocessor to: - receive the list of claims extracted from the JWT - use information like the `sub` (subject) claim to look up the user in an external database or service - insert additional data in the claims list - return the claims list to the router -For example, if you use this [router configuration](./overview#yaml-config-file): +For example, if you use this [router configuration](/router/configuration/overview#yaml-config-file): ```yaml title="router.yaml" authentication: @@ -417,7 +411,7 @@ The coprocessor can then look up the user with the identifier specified in the ` } ``` -For more information, refer to [the coprocessor documentation](../customizations/coprocessor/). +For more information, refer to [the coprocessor documentation](/router/customizations/coprocessor/). @@ -745,13 +739,13 @@ This matching strategy is necessary because some identity providers (IdPs) don't Because the GraphOS Router handles validating incoming JWTs, you rarely need to pass those JWTs to individual subgraphs in their entirety. Instead, you usually want to [pass JWT _claims_ to subgraphs](#example-forwarding-claims-to-subgraphs-as-headers) to enable fine-grained access control. -If you _do_ need to pass entire JWTs to subgraphs, you can do so via the GraphOS Router's general-purpose [HTTP header propagation settings](./header-propagation). +If you _do_ need to pass entire JWTs to subgraphs, you can do so via the GraphOS Router's general-purpose [HTTP header propagation settings](/graphos/routing/header-propagation). ## Observability -If your router enables [tracing](./telemetry/exporters/tracing/overview), the JWT authentication plugin has its own tracing span: `authentication_plugin` +If your router enables [tracing](/router/configuration/telemetry/exporters/tracing/overview), the JWT authentication plugin has its own tracing span: `authentication_plugin` -If your router enables [metrics collection via Prometheus](./telemetry/exporters/metrics/prometheus), the JWT authentication plugin provides and exports the following metrics: +If your router enables [metrics collection via Prometheus](/router/configuration/telemetry/exporters/metrics/prometheus), the JWT authentication plugin provides and exports the following metrics: - `apollo_authentication_failure_count` - `apollo_authentication_success_count` diff --git a/docs/source/configuration/persisted-queries.mdx b/docs/source/routing/security/persisted-queries.mdx similarity index 69% rename from docs/source/configuration/persisted-queries.mdx rename to docs/source/routing/security/persisted-queries.mdx index 0caabc7d1d..5befd7071c 100644 --- a/docs/source/configuration/persisted-queries.mdx +++ b/docs/source/routing/security/persisted-queries.mdx @@ -5,19 +5,13 @@ description: Secure your federated GraphQL API by creating an allowlist of trust minVersion: 1.25.0 --- - - ## Differences from automatic persisted queries -The Apollo Router Core also supports a related feature called [automatic persisted queries](./in-memory-caching#caching-automatic-persisted-queries-apq) (APQ). With APQ, clients can execute a GraphQL operation by sending the SHA256 hash of its operation string instead of the entire string. **APQ doesn't support safelisting** because the router updates its APQ cache over time with _any_ operations it receives. +The Apollo Router Core also supports a related feature called [automatic persisted queries](/router/configuration/in-memory-caching#caching-automatic-persisted-queries-apq) (APQ). With APQ, clients can execute a GraphQL operation by sending the SHA256 hash of its operation string instead of the entire string. **APQ doesn't support safelisting** because the router updates its APQ cache over time with _any_ operations it receives. For more details on differences between APQ and this feature, see the [GraphOS persisted queries documentation](/graphos/operations/persisted-queries#differences-from-automatic-persisted-queries). @@ -76,7 +70,7 @@ If used with the [`safelist`](#safelist) option, the router logs unregistered an -By default, the router [prewarms the query plan cache](./in-memory-caching#cache-warm-up) using all operations on the PQL when a new schema is loaded, but not at startup. Using the `experimental_prewarm_query_plan_cache` option, you can tell the router to prewarm the cache using the PQL on startup as well, or tell it not to prewarm the cache when reloading the schema. (This does not affect whether the router prewarms the query plan cache with recently-used operations from its in-memory cache.) Prewarming the cache means can reduce request latency by ensuring that operations are pre-planned when requests are received, but can make startup or schema reloads slower. +By default, the router [prewarms the query plan cache](/router/configuration/in-memory-caching#cache-warm-up) using all operations on the PQL when a new schema is loaded, but not at startup. Using the `experimental_prewarm_query_plan_cache` option, you can tell the router to prewarm the cache using the PQL on startup as well, or tell it not to prewarm the cache when reloading the schema. (This does not affect whether the router prewarms the query plan cache with recently-used operations from its in-memory cache.) Prewarming the cache means can reduce request latency by ensuring that operations are pre-planned when requests are received, but can make startup or schema reloads slower. ```yaml title="router.yaml" persisted_queries: @@ -116,7 +110,7 @@ apq: -To enable safelisting, you _must_ turn off [automatic persisted queries](./in-memory-caching#caching-automatic-persisted-queries-apq) (APQs). APQs let clients [register arbitrary operations at runtime](/graphos/operations/persisted-queries/#differences-from-automatic-persisted-queries) while safelisting restricts operations to those that have been explicitly registered. +To enable safelisting, you _must_ turn off [automatic persisted queries](/router/configuration/in-memory-caching#caching-automatic-persisted-queries-apq) (APQs). APQs let clients [register arbitrary operations at runtime](/graphos/operations/persisted-queries/#differences-from-automatic-persisted-queries) while safelisting restricts operations to those that have been explicitly registered. @@ -140,10 +134,10 @@ apq: -To enable safelisting, you _must_ turn off [automatic persisted queries](./in-memory-caching#caching-automatic-persisted-queries-apq) (APQs). APQs let clients [register arbitrary operations at runtime](/graphos/operations/persisted-queries/#differences-from-automatic-persisted-queries) while safelisting restricts operations to those that have been explicitly registered. +To enable safelisting, you _must_ turn off [automatic persisted queries](/router/configuration/in-memory-caching#caching-automatic-persisted-queries-apq) (APQs). APQs let clients [register arbitrary operations at runtime](/graphos/operations/persisted-queries/#differences-from-automatic-persisted-queries) while safelisting restricts operations to those that have been explicitly registered. ## Limitations -* **Unsupported with offline license**. An GraphOS Router using an [offline Enterprise license](../enterprise-features/#offline-enterprise-license) cannot use safelisting with persisted queries. The feature relies on Apollo Uplink to fetch persisted query manifests, so it doesn't work as designed when the router is disconnected from Uplink. +* **Unsupported with offline license**. An GraphOS Router using an [offline Enterprise license](/router/enterprise-features/#offline-enterprise-license) cannot use safelisting with persisted queries. The feature relies on Apollo Uplink to fetch persisted query manifests, so it doesn't work as designed when the router is disconnected from Uplink. diff --git a/docs/source/configuration/operation-limits.mdx b/docs/source/routing/security/request-limits.mdx similarity index 60% rename from docs/source/configuration/operation-limits.mdx rename to docs/source/routing/security/request-limits.mdx index 2f24ce620b..3cbe0ff552 100644 --- a/docs/source/configuration/operation-limits.mdx +++ b/docs/source/routing/security/request-limits.mdx @@ -1,24 +1,43 @@ --- -title: Enforcing Operation Limits in the GraphOS Router -subtitle: Set constraints on depth, height, aliases, and root fields -description: Ensure your GraphQL operations are secure with GraphOS Router's operation limits. Set constraints on depth, height, aliases, and root fields. +title: Request Limits +subtitle: Protect your router from requests exceeding network, parser, and operation-based limits +redirectFrom: + - /router/configuration/operation-limits/ --- - +For enhanced security, the GraphOS Router can reject requests that violate any of the following kinds of limits: + +- Operation-based semantic limits +- Network-based limits +- Parser-based lexical limits + +```yaml title="router.yaml" +limits: + # Network-based limits + http_max_request_bytes: 2000000 # Default value: 2 MB + + # Parser-based limits + parser_max_tokens: 15000 # Default value + parser_max_recursion: 500 # Default value + + # Operation-based limits (Enterprise only) + max_depth: 100 + max_height: 200 + max_aliases: 30 + max_root_fields: 20 +``` + +## Operation-based limits You can define **operation limits** in your router's configuration to reject potentially malicious requests. An operation that exceeds _any_ specified limit is rejected (unless you run your router in [`warn_only` mode](#warn_only-mode)). -## Setup +### Setup -To use operation limits, you must run v1.17 or later of the GraphOS Router. [Download the latest version.](../quickstart#download-options) +To use operation limits, you must run v1.17 or later of the Apollo Router. [Download the latest version.](/graphos/reference/router/self-hosted-install/#download-options) -You define operation limits in your router's [YAML config file](./overview/#yaml-config-file), like so: +You define operation limits in your router's [YAML config file](/graphos/reference/router/configuration#yaml-config-file), like so: ```yaml title="router.yaml" limits: @@ -33,9 +52,9 @@ limits: Each limit takes an integer value. You can define any combination of [supported limits](#supported-limits). -## Supported limits +### Supported limits -### `max_depth` +#### `max_depth` Limits the deepest nesting of selection sets in an operation, including fields in fragments. @@ -57,7 +76,7 @@ fragment bookDetails on Book { } ``` -### `max_height` +#### `max_height` Limits the number of unique fields included in an operation, including fields of fragments. If a particular field is included _multiple_ times via aliases, it's counted only _once_. @@ -75,7 +94,7 @@ query GetUser { Each unique field increments an operation's height by one, regardless of that field's return type (scalar, object, or list). -### `max_aliases` +#### `max_aliases` Limits the total number of aliased fields in an operation, including fields of fragments. @@ -93,7 +112,7 @@ query GetUser { Each aliased field increments the alias count by one, regardless of that field's return type (scalar, object, or list). -### `max_root_fields` +#### `max_root_fields` Limits the number of root fields in an operation, including root fields in fragments. If a particular root field is included _multiple_ times via aliases, _each usage_ is counted. @@ -113,7 +132,7 @@ query GetTopProducts { } ``` -## `warn_only` mode +### `warn_only` mode If you run your router in `warn_only` mode, operations that exceed defined limits are _not_ rejected. Instead, the router processes these operations as usual and emits a `WARN` trace that notes all exceeded limits, like so: @@ -123,14 +142,14 @@ If you run your router in `warn_only` mode, operations that exceed defined limit Running in `warn_only` mode can be useful while you're testing to determine the most appropriate limits to set for your supergraph. -You can enable or disable `warn_only` mode in your router's [YAML config file](./overview/#yaml-config-file), like so: +You can enable or disable `warn_only` mode in your router's [YAML config file](/graphos/reference/router/configuration#yaml-config-file), like so: ```yaml title="router.yaml" limits: warn_only: true # warn_only mode always enabled ``` -## Response format for exceeded limits +### Response format for exceeded limits Whenever your router rejects a request because it exceeds an operation limit, the router responds with a 400 HTTP status code and a standard GraphQL error response body: @@ -151,13 +170,13 @@ Whenever your router rejects a request because it exceeds an operation limit, th If you run your router in [`warn_only` mode](#warn_only-mode), the router logs the limit violation but executes the operation as normal, returning a 200 status code with the expected response. -## Using telemetry to set operation limits +### Using telemetry to set operation-based limits Router telemetry can help you set operation limits, especially when you have a large number of existing operations. You can measure incoming operations over a fixed duration, then use the captured data as a baseline configuration. -### Logging values +#### Logging values -To log limit information about every operation, you can configure the router with a [custom event](/router/configuration/telemetry/instrumentation/events#custom-events) to log the values of aliases, depth, height, and root_fields for each operation: +To log limit information about every operation, you can configure the router with a [custom event](/graphos/reference/router/telemetry/instrumentation/events#custom-events) to log the values of aliases, depth, height, and root_fields for each operation: ```yaml title="router.yaml" telemetry: @@ -186,9 +205,9 @@ For a large amount of traffic, you may prefer to collect and export metrics to y -### Collecting metrics +#### Collecting metrics -To capture and view metrics to help set your operation limits, you can configure the router to collect [custom metrics](/router/configuration/telemetry/instrumentation/instruments#custom-instruments) on the values of aliases, depth, height, and root_fields for each operation: +To capture and view metrics to help set your operation limits, you can configure the router to collect [custom metrics](/graphos/reference/router/telemetry/instrumentation/instruments#custom-instruments) on the values of aliases, depth, height, and root_fields for each operation: ```yaml title="router.yaml" telemetry: @@ -237,5 +256,60 @@ telemetry: unit: number description: "Root fields for an operation" ``` +You should also configure the router to [export metrics](/graphos/reference/router/telemetry/metrics-exporters/overview) to your APM tool. + +## Network-based limits + +### `http_max_request_bytes` + +Limits the amount of data read from the network for the body of HTTP requests, +to protect against unbounded memory consumption. +This limit is checked before JSON parsing. +Both the GraphQL document and associated variables count toward it. + +The default value is `2000000` bytes, 2 MB. + +Before increasing this limit significantly consider testing performance +in an environment similar to your production, especially if some clients are untrusted. +Many concurrent large requests could cause the router to run out of memory. + +## Parser-based limits + +### `parser_max_tokens` + +Limits the number of tokens a query document can include. This counts _all_ tokens, including both [lexical and ignored tokens](https://spec.graphql.org/October2021/#sec-Language.Source-Text.Lexical-Tokens). -You should also configure the router to [export metrics](/router/configuration/telemetry/exporters/metrics/overview) to your APM tool. +The default value is `15000`. + +### `parser_max_recursion` + +Limits the deepest level of recursion allowed by the router's GraphQL parser to prevent stack overflows. This corresponds to the deepest nesting level of any single GraphQL operation or fragment defined in a query document. + +The default value is `500`. + +In the example below, the `GetProducts` operation has a recursion of three, and the `ProductVariation` fragment has a recursion of two. Therefore, the _max_ recursion of the query document is three. + +```graphql +query GetProducts { + allProducts { #1 + ...productVariation + delivery { #2 + fastestDelivery #3 + } + } +} + +fragment ProductVariation on Product { + variation { #1 + name #2 + } +} +``` + +Note that the router calculates the recursion depth for each operation and fragment _separately_. Even if a fragment is included in an operation, that fragment's recursion depth does not contribute to the _operation's_ recursion depth. + + + +In versions of the Apollo Router prior to 1.17, this limit was defined via the config option `experimental_parser_recursion_limit`. + + diff --git a/docs/source/routing/security/router-authentication.mdx b/docs/source/routing/security/router-authentication.mdx new file mode 100644 index 0000000000..cdcc22ef4e --- /dev/null +++ b/docs/source/routing/security/router-authentication.mdx @@ -0,0 +1,214 @@ +--- +title: Authenticating Requests with the GraphOS Router +subtitle: Use authorization and authentication strategies to secure your graph +description: Combine authorization and authentication strategies with the GraphOS Router to secure your graph through defense in depth. +published: 2022-06-13 +id: TN0004 +tags: [server, router, auth] +redirectFrom: + - /technotes/TN0004-router-authentication/ +--- + + + +Self-hosting the GraphOS Router is limited to [GraphOS Enterprise plans](https://www.apollographql.com/pricing). Other plan types use [managed cloud routing with GraphOS](/graphos/cloud-routing). Check out the [pricing page](https://www.apollographql.com/pricing#graphos-router) to learn more. + + + + + +If you're an enterprise customer looking for more material on this topic, try the [Enterprise best practices: Router extensibility](https://www.apollographql.com/tutorials/router-extensibility) course on Odyssey. + +Not an enterprise customer? [Learn about GraphOS for Enterprise.](https://www.apollographql.com/pricing) + + + +When using the router as the entry point to your federated supergraph, you have a few options for authenticating incoming client requests: + +- [Use authorization directives](#use-authorization-directives) +- [Delegate authentication to your subgraphs.](#authenticate-in-subgraphs) +- [Use the JWT authentication plugin](#use-the-jwt-authentication-plugin) to your supergraph. +- [Use a coprocessor](#use-a-coprocessor). + +In fact, we recommend you [combine all three strategies](#combining-authentication-strategies) to create a more robust authentication system! + +## Use authorization directives + +In addition to the approaches outlined below, you can use [authorization directives](/graphos/routing/security/authorization/) to enforce authorization at the router layer. +This allows you to authorize requests prior to them hitting your subgraphs saving on bandwidth and processing time. + + + +This is an [Enterprise feature](/router/enterprise-features) of the GraphOS Router. +It requires an organization with a [GraphOS Enterprise plan](https://www.apollographql.com/pricing/). + + + +```mermaid +sequenceDiagram + Client->>Router: Request with token + note over Router: Validate request + alt Request is invalid + Router->>Client: Respond 401 Unauthorized + else Request is valid + Router->>Subgraph: Request Data + end +``` + +Once the request's claims are made available via the JWT validation or a coprocessor, they can be used to match against the required type and field scopes to enforce authorization policies. + +```graphql +# Request's authorization claims must contain `read:users` +type Query { + users: [User!]! @requiresScopes(scopes: [["read:users"]]) +} + +# Request must be authenticated +type Mutation { + updateUser(input: UpdateUserInput!): User! @authenticated +} +``` + +Pros: + +- Validating authorization before processing requests enables the early termination of unauthorized requests reducing the load on your services +- Declarative approach that can be adopted and maintained by each subgraph while enforced centrally + +Cons + +- Schema updates will need to be made to each subgraph to opt into this authorization model + +## Authenticate in subgraphs + +The simplest authentication strategy is to delegate authentication to your individual subgraph services. + +```mermaid +sequenceDiagram + Client->>Router: Request with token + Router->>Subgraph: Request with token + note over Subgraph: Authenticate request with token +``` + +To pass `Authentication` headers from client requests to your subgraphs, add the following to your router's YAML configuration file: + +```yaml +headers: + all: + request: + - propagate: + named: authorization +``` + +#### Pros + +- Requires minimal changes to your router configuration. +- Can take advantage of existing authentication code in subgraphs, which is often tied to authorization logic for data sources. + +#### Cons + +- Each subgraph that contributes to resolving a request needs to authenticate that request. +- If subgraphs are written in different languages, maintaining consistent authentication code for each is complex. + +## Use the JWT Authentication plugin + +As of router v1.13, you can use the [JWT Authentication plugin](/router/configuration/authn-jwt) to validate JWT-based authentication tokens in your supergraph. + + + +```mermaid +sequenceDiagram + Client->>Router: Request with JWT + Router->>JWKS Endpoint: Fetch key set + JWKS Endpoint->>Router: Public keys + note over Router: Validate JWT + note over Router: Extract claims in Rhai + Router->>Subgraph: Request with extracted claims in headers + note over Subgraph: Check claims on headers +``` + +```yaml +authentication: + jwt: + jwks: + - url: https://dev-zzp5enui.us.auth0.com/.well-known/jwks.json +``` + +Pros: + +- The router prevents unauthenticated requests from reaching your subgraphs. +- The router can extract claims from the JWT and pass them to your subgraphs as headers, reducing logic needed in your subgraphs. + +Cons: + +- It supports only JWT-based authentication with keys from a JWKS endpoint. + +## Use a coprocessor + +If you have a custom authentication strategy, you can use a [coprocessor](/graphos/routing/customization/coprocessor) to implement it. + + + +```mermaid +sequenceDiagram + Client->>Router: Request with token + Router->>Coprocessor: Request with headers and context + note over Coprocessor: Validate request + alt Request is invalid + Coprocessor->>Router: Respond { control: { break: 401 } } + else Request is valid + Coprocessor->>Router: Respond { control: "continue" } + note over Coprocessor: Can also add new headers + end + Router->>Subgraph: Request with new headers + note over Subgraph: Check claims on headers +``` + +```yaml +coprocessor: + url: http://127.0.0.1:8081 + router: + request: + headers: true +``` + +This example coprocessor is written in Node.js and uses Express: + +```js +const app = express(); +app.use(bodyParser.json()); +app.post('/', async (req, res) => { + const {headers} = req.body; + const token = headers.authorization; + const isValid = await validateToken(token); + if (!isValid) { + res.json({ + ...req.body, + control: {break: 401} + }); + } else { + res.json({ + ...req.body, + control: 'continue', + headers: {'x-claims': extractClaims(token)} + }); + } +}); +``` + +Pros: + +- You can implement any authentication strategy in any language or framework, as long as the coprocessor provides an HTTP endpoint. +- You can use the coprocessor to add headers to requests, which can be used by your subgraphs for additional authorization. + +Cons: + +- The initial lift of implementing a coprocessor is non-trivial, but once it's in place you can leverage it for any number of router customizations. + +## Combining authentication strategies + +You can combine the strategies to handle a number of authentication requirements and practice "defense-in-depth": + +1. Use the JWT Authentication plugin to validate JWT-based authentication tokens. +2. Use auth directives to enforce authentication and authorization and at the supergraph layer +3. Use a coprocessor to identify traffic using a legacy authentication strategy and convert legacy session tokens to JWTs. +4. Forward JWTs to subgraphs for additional authorization. diff --git a/docs/source/configuration/authn-subgraph.mdx b/docs/source/routing/security/subgraph-authentication.mdx similarity index 94% rename from docs/source/configuration/authn-subgraph.mdx rename to docs/source/routing/security/subgraph-authentication.mdx index 3d06ef578f..d138e981d7 100644 --- a/docs/source/configuration/authn-subgraph.mdx +++ b/docs/source/routing/security/subgraph-authentication.mdx @@ -5,12 +5,6 @@ description: Secure communication to AWS subgraphs via the Apollo GraphOS Router minVersion: 1.27.0 --- - - The GraphOS Router and Apollo Router Core support subgraph request authentication and key rotation via [AWS Signature Version 4](https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html) (SigV4). This allows you to secure communication to AWS subgraphs by making sure a subgraph request was made by the router, and the payload hasn't been tampered with. diff --git a/docs/source/routing/security/tls.mdx b/docs/source/routing/security/tls.mdx new file mode 100644 index 0000000000..97d1af2187 --- /dev/null +++ b/docs/source/routing/security/tls.mdx @@ -0,0 +1,135 @@ +--- +title: TLS +subtitle: Secure client-side and subgraph-side communications +redirectFrom: + - /router/configuration/overview/#tls +--- + +The GraphOS Router supports TLS to authenticate and encrypt communications, both on the client side and the subgraph side. It works automatically on the subgraph side if the subgraph URL starts with `https://`. + +## Configuring TLS + +TLS support is configured in the `tls` section, under the `supergraph` key for the client side, and the `subgraph` key for the subgraph side, with configuration possible for all subgraphs and overriding per subgraph. + +The list of supported TLS versions and algorithms is static, it cannot be configured. + +Supported TLS versions: +* TLS 1.2 +* TLS 1.3 + +Supported cipher suites: +* TLS13_AES_256_GCM_SHA384 +* TLS13_AES_128_GCM_SHA256 +* TLS13_CHACHA20_POLY1305_SHA256 +* TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 +* TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 +* TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 +* TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 +* TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 +* TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + +Supported key exchange groups: +* X25519 +* SECP256R1 +* SECP384R1 + +## TLS termination + +Clients can connect to the router directly over HTTPS, without terminating TLS in an intermediary. You can configure this in the `tls` configuration section: + +```yaml +tls: + supergraph: + certificate: ${file./path/to/certificate.pem} + certificate_chain: ${file./path/to/certificate_chain.pem} + key: ${file./path/to/key.pem} +``` + +To set the file paths in your configuration with Unix-style expansion, you can follow the examples in the [variable expansion](#variable-expansion) guide. + +The router expects the file referenced in the `certificate_chain` value to be a combination of several PEM certificates concatenated together into a single file (as is commonplace with Apache TLS configuration). + +## Overriding certificate authorities for subgraphs + +The router verifies TLS connections to subgraphs using the list of certificate authorities the system provides. You can override this list with a combination of global and per-subgraph settings: + +```yaml +tls: + subgraph: + # Use these certificate authorities unless overridden per-subgraph + all: + certificate_authorities: "${file./path/to/ca.crt}" + # Override global setting for individual subgraphs + subgraphs: + products: + certificate_authorities: "${file./path/to/product_ca.crt}" +``` + +The router expects the file referenced in the `certificate_chain` value to be a combination of several PEM certificates concatenated together into a single file (as is commonplace with Apache TLS configuration). + +You can only configure these certificates via the router's configuration since using `SSL_CERT_FILE` also overrides certificates for sending telemetry and communicating with Apollo Uplink. + +If the subgraph is presenting a self-signed certificate, it must be generated with the proper file extension and with `basicConstraints` turned off. You can generate it with the following command line command from a certificate signing request, in this example, `server.csr`: + +``` +openssl x509 -req -in server.csr -signkey server.key -out server.crt -extfile v3.ext +``` + +You can generate a `v3.ext` extension file like so: + +``` +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer:always +# this has to be turned off +# basicConstraints = CA:TRUE +keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign +subjectAltName = DNS:local.apollo.dev +issuerAltName = issuer:copy +``` + + + +Make sure to change the `subjectAltName` field to the subgraph's name. + + + +This produces the file as `server.crt` which can be used in `certificate_authorities`. + +## TLS client authentication for subgraph requests + +The router supports mutual TLS authentication (mTLS) with the subgraphs. This means that it can authenticate itself to the subgraph using a certificate chain and a cryptographic key. It can be configured as follows: + +```yaml +tls: + subgraph: + # Use these certificates and key unless overridden per-subgraph + all: + client_authentication: + certificate_chain: ${file./path/to/certificate_chain.pem} + key: ${file./path/to/key.pem} + # Override global setting for individual subgraphs + subgraphs: + products: + client_authentication: + certificate_chain: ${file./path/to/certificate_chain.pem} + key: ${file./path/to/key.pem} +``` + +## Redis TLS configuration + +For Redis TLS connections, you can set up a client certificate or override the root certificate authority by configuring `tls` in your router's [YAML config file](https://www.apollographql.com/docs/router/overview/#yaml-config-file). For example: + +```yaml +apq: + router: + cache: + redis: + urls: [ "rediss://redis.example.com:6379" ] + #highlight-start + tls: + certificate_authorities: ${file./path/to/ca.crt} + client_authentication: + certificate_chain: ${file./path/to/certificate_chain.pem} + key: ${file./path/to/key.pem} + #highlight-end +``` diff --git a/docs/source/containerization/docker.mdx b/docs/source/routing/self-hosted/containerization/docker.mdx similarity index 94% rename from docs/source/containerization/docker.mdx rename to docs/source/routing/self-hosted/containerization/docker.mdx index 11aacdc11a..605b8723c1 100644 --- a/docs/source/containerization/docker.mdx +++ b/docs/source/routing/self-hosted/containerization/docker.mdx @@ -4,7 +4,7 @@ subtitle: Run the router container image in Docker description: Run the Apollo Router Core container image in Docker with examples covering basic setup, configuration overrides, debugging, and building custom Docker images. --- -import ElasticNotice from '../../shared/elastic-notice.mdx'; +import ElasticNotice from '../../../../shared/elastic-notice.mdx'; This guide provides the following examples of running an Apollo Router Core container image in Docker: @@ -22,7 +22,7 @@ The exact image version to use depends on which release you wish to use. In the ## Basic example running router in Docker -To run the router, your Docker container must have the [`APOLLO_GRAPH_REF`](../configuration/overview#apollo_graph_ref) and [`APOLLO_KEY`](../configuration/overview#apollo_key) environment variables set to your graph ref and API key, respectively. +To run the router, your Docker container must have the [`APOLLO_GRAPH_REF`](/router/configuration/overview#apollo_graph_ref) and [`APOLLO_KEY`](/router/configuration/overview#apollo_key) environment variables set to your graph ref and API key, respectively. Here's a basic example of running a router image in Docker. Make sure to replace `` with whichever version you want to use, such as `v1.32.0`. @@ -36,7 +36,7 @@ docker run -p 4000:4000 \ This command downloads your supergraph schema from Apollo and uses a default configuration that listens for connections on port `4000`. -For more complex configurations, such as overriding subgraph URLs or propagating headers, see [Router Configuration](../configuration/overview/). +For more complex configurations, such as overriding subgraph URLs or propagating headers, see [Router Configuration](/router/configuration/overview/). ## Override the configuration @@ -65,7 +65,7 @@ In this example we are mounting a file from the host system (`/home/user/router. ## Passing command-line arguments to the router binary -By default, the `router` command invoked inside the published container doesn't set any of the [available command-line options](../configuration/overview#command-line-options). To set them, append the desired option(s) to the `docker run` command. +By default, the `router` command invoked inside the published container doesn't set any of the [available command-line options](/router/configuration/overview#command-line-options). To set them, append the desired option(s) to the `docker run` command. For example, to start the router using the `--log debug` option, use the following `docker run` command with the option added at the end: diff --git a/docs/source/containerization/overview.mdx b/docs/source/routing/self-hosted/containerization/index.mdx similarity index 90% rename from docs/source/containerization/overview.mdx rename to docs/source/routing/self-hosted/containerization/index.mdx index 44c2302952..0b9a452de0 100644 --- a/docs/source/containerization/overview.mdx +++ b/docs/source/routing/self-hosted/containerization/index.mdx @@ -4,7 +4,7 @@ subtitle: Run router images in containers description: Containerize the Apollo GraphOS Router for portability and scalability. Choose from default or debug images. Deploy in Kubernetes or run in Docker. --- -import ElasticNotice from '../../shared/elastic-notice.mdx'; +import ElasticNotice from '../../../../shared/elastic-notice.mdx'; Apollo provides container images of the Apollo Router Core that you can self-host and run with GraphOS as GraphOS Routers. By containerizing the router, you can run it in a cluster and leverage the portability, scalability, and high availability benefits of containerization. Containers can also simplify and speed up local development. @@ -27,5 +27,5 @@ A router image has the following layout: The default behavior of a router image is suitable for a basic deployment or development scenario. For examples of customizing and deploying router images in specific environments, see the guides for: -* [Deploying in Kubernetes](./kubernetes/). -* [Running in Docker](./docker/) +* [Deploying in Kubernetes](/router/containerization/kubernetes/). +* [Running in Docker](/router/containerization/docker/) diff --git a/docs/source/containerization/kubernetes.mdx b/docs/source/routing/self-hosted/containerization/kubernetes.mdx similarity index 87% rename from docs/source/containerization/kubernetes.mdx rename to docs/source/routing/self-hosted/containerization/kubernetes.mdx index 7ad8ffa50a..344a982aa3 100644 --- a/docs/source/containerization/kubernetes.mdx +++ b/docs/source/routing/self-hosted/containerization/kubernetes.mdx @@ -4,9 +4,9 @@ subtitle: Self-hosted deployment of the router in Kubernetes description: Deploy the Apollo GraphOS Router or Apollo Router Core in Kubernetes using Helm charts. Customize configurations, enable metrics, and choose values for migration. --- -import ElasticNotice from '../../shared/elastic-notice.mdx'; -import HelmShowOutput from '../../shared/helm-show-router-output.mdx'; -import CoprocTypicalConfig from '../../shared/coproc-typical-config.mdx'; +import ElasticNotice from '../../../../shared/elastic-notice.mdx'; +import HelmShowOutput from '../../../../shared/helm-show-router-output.mdx'; +import CoprocTypicalConfig from '../../../../shared/coproc-typical-config.mdx'; Learn how to deploy a self-hosted router (GraphOS Router or Apollo Router Core) in Kubernetes using Helm charts. @@ -46,7 +46,7 @@ The path to the OCI router chart is `oci://ghcr.io/apollographql/helm-charts/rou -You customize a deployed router with the same [command-line options and YAML configuration](../configuration/overview) but under different Helm CLI options and YAML keys. +You customize a deployed router with the same [command-line options and YAML configuration](/router/configuration/overview) but under different Helm CLI options and YAML keys. ## Basic deployment @@ -54,8 +54,8 @@ Follow this guide to deploy the Router using Helm to install the basic chart pr Each router chart has a `values.yaml` file with router and deployment settings. The released, unedited file has a few explicit settings, including: -* Default container ports for the router's [HTTP server](../configuration/overview/#listen-address), [health check endpoint](../configuration/health-checks), and [metrics endpoint](../configuration/telemetry/exporters/metrics/overview). -* A command-line argument to enable [hot reloading of the router](../configuration/overview/#--hr----hot-reload). +* Default container ports for the router's [HTTP server](/router/configuration/overview/#listen-address), [health check endpoint](/router/configuration/health-checks), and [metrics endpoint](/router/configuration/telemetry/exporters/metrics/overview). +* A command-line argument to enable [hot reloading of the router](/router/configuration/overview/#--hr----hot-reload). * A single replica. @@ -104,7 +104,7 @@ To manage the system resources you need to deploy the router on Kubernetes: ### Set up graph -Set up your self-hosted graph and get its [graph ref](../configuration/overview/#apollo_graph_ref) and [API key](../configuration/overview/#apollo_graph_ref). +Set up your self-hosted graph and get its [graph ref](/router/configuration/overview/#apollo_graph_ref) and [API key](/router/configuration/overview/#apollo_graph_ref). If you need a guide to set up your graph, you can follow [the self-hosted router quickstart](/graphos/quickstart/self-hosted) and complete [step 1 (Set up Apollo tools)](/graphos/quickstart/self-hosted/#1-set-up-apollo-tools), [step 4 (Obtain your subgraph schemas)](/graphos/quickstart/self-hosted/#4-obtain-your-subgraph-schemas), and [step 5 (Publish your subgraph schemas)](/graphos/quickstart/self-hosted/#5-publish-your-subgraph-schemas). @@ -117,8 +117,8 @@ helm install --namespace --set managedFederation.apiKey=" ## Deploy with metrics endpoints -The router supports [metrics endpoints for Prometheus and OpenTelemetry protocol (OTLP)](../configuration/telemetry/exporters/metrics/overview). A [basic deployment](#basic-deployment) doesn't enable metrics endpoints, because the router chart disables both Prometheus (explicitly) and OTLP (by omission). +The router supports [metrics endpoints for Prometheus and OpenTelemetry protocol (OTLP)](/router/configuration/telemetry/exporters/metrics/overview). A [basic deployment](#basic-deployment) doesn't enable metrics endpoints, because the router chart disables both Prometheus (explicitly) and OTLP (by omission). To enable metrics endpoints in your deployed router through a YAML configuration file: @@ -176,20 +176,20 @@ To enable metrics endpoints in your deployed router through a YAML configuration ## Deploy with Rhai scripts -The router supports [Rhai scripting](../customizations/rhai) to add custom functionality. +The router supports [Rhai scripting](/graphos/routing/customization/rhai) to add custom functionality. Enabling Rhai scripts in your deployed router requires mounting an extra volume for your Rhai scripts and getting your scripts onto the volume. That can be done by following steps in [a separate example for creating a custom in-house router chart](https://github.com/apollographql/in-house-router-example). The example creates a new (in-house) chart that wraps (and depends on) the released router chart, and the new chart has templates that add the necessary configuration to allow Rhai scripts for a deployed router. ## Deploy with a coprocessor -The router supports [external coprocessing](../customizations/coprocessor) to run custom logic on requests throughout the [router's request-handling lifecycle](../customizations/rhai/#router-request-lifecycle). +The router supports [external coprocessing](/router/customizations/coprocessor) to run custom logic on requests throughout the [router's request-handling lifecycle](/graphos/routing/customization/rhai/#router-request-lifecycle). A deployed coprocessor has its own application image and container in the router pod. To configure a coprocessor and its container for your deployed router through a YAML configuration file: 1. Create a YAML file, `my_values.yaml`, to contain additional values that override default values. -1. Edit `my_values.yaml` to configure a coprocessor for the router. For reference, follow the [typical](../customizations/coprocessor#typical-configuration) and [minimal](../customizations/coprocessor#minimal-configuration) configuration examples, and apply them to `router.configuration.coprocessor`. +1. Edit `my_values.yaml` to configure a coprocessor for the router. For reference, follow the [typical](/router/customizations/coprocessor#typical-configuration) and [minimal](/router/customizations/coprocessor#minimal-configuration) configuration examples, and apply them to `router.configuration.coprocessor`. @@ -239,7 +239,7 @@ This is not specifically a router issue and Istio has instructions on how to man ## Configure for migration from gateway -When [migrating from `@apollo/gateway` to the router](../migrating-from-gateway), consider the following tips to maximize the compatibility of your router deployment. +When [migrating from `@apollo/gateway` to the router](/router/migrating-from-gateway), consider the following tips to maximize the compatibility of your router deployment. ### Increase maximum request bytes diff --git a/docs/source/routing/self-hosted/containerization/optimize-build.mdx b/docs/source/routing/self-hosted/containerization/optimize-build.mdx new file mode 100644 index 0000000000..90e2dc3dd4 --- /dev/null +++ b/docs/source/routing/self-hosted/containerization/optimize-build.mdx @@ -0,0 +1,58 @@ +--- +title: Optimizing Custom GraphOS Router Builds +subtitle: Enhance performance, minimize build time, and address system requirements +description: Recommendations and considerations for minimizing build time when using custom Apollo GraphOS Router builds. +published: 2023-01-19 +id: TN0030 +tags: [router] +redirectFrom: + - /technotes/TN0030-optimizing-router-builds/ +--- + +While running the GraphOS Router in production has great performance, this comes at the cost of increased build time and higher system requirements when compiling from source. + +Building the router including custom plugins from source is a memory-expensive process, and as such it's not suited for all build environments. + +Some cloud build pipelines such as Google Cloud Build, will require changes to the default build configuration to increase the memory and CPU capacity of the build worker pool. + +The router will also download a large collection of dependencies during the build process each build by default. We can use [Kaniko](https://github.com/GoogleContainerTools/kaniko) to cache intermediate build layers. + +In this example for Google Cloud Build, we have replaced the standard docker [gcr.io/cloud-builders/docker](http://gcr.io/cloud-builders/docker) container image, with [gcr.io/kaniko-project/executor](http://gcr.io/kaniko-project/executor). +This is all that's needed to enable caching of the intermediate build steps. Each step will be pushed to the destination container repo as soon as each layer is built, so even failed builds will contribute to increased build speeds as successful layers are cached. + +We also changed the default `options.machineType` value to `E2_HIGHCPU_8`, this is because the default worker pool doesn't have the CPU or memory resources necessary to compile the router. + +```yaml +#cloudbuild.yaml + +steps: + - id: Build Router + name: 'gcr.io/kaniko-project/executor:latest' + args: + - '--cache=true' + - '--dockerfile=$_DOCKERFILE' + - '--context=dir://$_IMAGE_NAME' + - >- + --destination=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_IMAGE_NAME:$COMMIT_SHA + - id: Deploy Router + name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim' + entrypoint: gcloud + args: + - run + - services + - update + - $_SERVICE_NAME + - '--platform=managed' + - '--image=$_GCR_HOSTNAME/$PROJECT_ID/$REPO_NAME/$_IMAGE_NAME:$COMMIT_SHA' + - '--region=$_DEPLOY_REGION' + - '--quiet' +options: + machineType: E2_HIGHCPU_8 +substitutions: + _DOCKERFILE: custom-router/Dockerfile + _IMAGE_NAME: custom-router + _SERVICE_NAME: apollo-router + _DEPLOY_REGION: northamerica-northeast1 + _GCR_HOSTNAME: northamerica-northeast1-docker.pkg.dev + _PLATFORM: managed +``` diff --git a/docs/source/configuration/health-checks.mdx b/docs/source/routing/self-hosted/health-checks.mdx similarity index 97% rename from docs/source/configuration/health-checks.mdx rename to docs/source/routing/self-hosted/health-checks.mdx index e6f54857d6..6a2566c0c5 100644 --- a/docs/source/configuration/health-checks.mdx +++ b/docs/source/routing/self-hosted/health-checks.mdx @@ -97,7 +97,7 @@ In Kubernetes, you can configure health checks by setting `readinessProbe` and ` port: 8088 # ... snipped for partial example ... ``` -See a more complete example in our [Kubernetes documentation](../containerization/kubernetes/). +See a more complete example in our [Kubernetes documentation](/router/containerization/kubernetes/). ## Using with Docker Docker has a `HEALTHCHECK` instruction that tells Docker how to test whether a container is still working. These are defined in the `Dockerfile` when building your container: ``` diff --git a/docs/source/routing/self-hosted/index.mdx b/docs/source/routing/self-hosted/index.mdx new file mode 100644 index 0000000000..1f7b68e428 --- /dev/null +++ b/docs/source/routing/self-hosted/index.mdx @@ -0,0 +1,49 @@ +--- +title: Self-Hosted Router +subtitle: Host and deploy routers in your own infrastructure +description: Distribute operations efficiently across microservices in your federated GraphQL API with the Apollo GraphOS Router or Apollo Router Core. Configure caching, security features, and more. +--- + +A self-hosted GraphOS Router or Apollo Router Core enables you to fully manage the runtime infrastructure and deployments of your supergraph. + +```mermaid +flowchart LR; + clients(Clients); + subgraph "Your infrastructure"; + router(["Router"]); + serviceB[Products
API]; + serviceC[Reviews
API]; + router -->|Sub-query| serviceB & serviceC; + end; + clients -.->|Query| router; + class clients secondary; +``` + + + +Self-hosting the GraphOS Router is limited to [GraphOS Enterprise plans](https://www.apollographql.com/pricing). Other plan types use [managed cloud routing with GraphOS](/graphos/cloud-routing). Check out the [pricing page](https://www.apollographql.com/pricing#graphos-router) to learn more. + + + +## Downloading and installing a self-hosted router + +Apollo provides the router as both a binary and as images to run in your containerized deployments. + +### Router binary + +Apollo provides a binary of the router for multiple platforms. You can download the router bundle, extract the router binary, and run it. + +To learn more, follow the steps in the [self-hosted router installation](/graphos/reference/router/self-hosted-install) reference to run a router binary with a sample supergraph schema. + +### Router container image + +Apollo provides container images of the router to deploy in self-hosted environments. The router images are hosted on GitHub in its container repository. Each router release includes both production and debug images. + +To learn more, go to the [containerization overview](/graphos/routing/self-hosted/containerization). + +- If running with Docker, go to the [Docker](/graphos/routing/self-hosted/containerization/docker) docs to learn how to run router images. +- If running with Kubernetes, go to the [Kubernetes](/graphos/routing/self-hosted/containerization/kubernetes) docs to learn to deploy with router Helm charts. + +## Next steps + +- To prepare your routers for production deployment, follow the guides in [Production Readiness](/graphos/platform/production-readiness/checklist) docs. diff --git a/docs/source/routing/self-hosted/resource-estimator.mdx b/docs/source/routing/self-hosted/resource-estimator.mdx new file mode 100644 index 0000000000..26d8e363d0 --- /dev/null +++ b/docs/source/routing/self-hosted/resource-estimator.mdx @@ -0,0 +1,28 @@ +--- +title: Router Resource Estimator +subtitle: Estimate the system resources to allocate for the GraphOS Router +description: Estimate the system resources you need to allocate for the Apollo GraphOS Router to run production traffic. +published: 2023-12-15 +id: TN0045 +toc: false +tags: [router] +redirectFrom: + - /technotes/TN0045-router_resource_estimator/ +--- + +import RouterResourceEstimator from '../../components/TechNotes/RouterResourceEstimator'; + +The _router resource estimator_ estimates the system resources you need to allocate for the GraphOS Router to run production traffic. The resource estimator can help you get a starting baseline that you can then iterate on. + +## Usage + +To use the estimator: + +1. Enter your estimated **request rate per second** and **peak request rate per second**. +2. Adjust the other parameters to match your estimated production load. + - When selecting the **number of instances**, select fewer for efficiency, more for safety. +3. Be sure to test and iterate. + +## Router resource estimator + + diff --git a/docs/source/routing/self-hosted/resource-management.mdx b/docs/source/routing/self-hosted/resource-management.mdx new file mode 100644 index 0000000000..0e40121313 --- /dev/null +++ b/docs/source/routing/self-hosted/resource-management.mdx @@ -0,0 +1,61 @@ +--- +title: Managing GraphOS Router Resources in Kubernetes +subtitle: Recommendations and considerations for application pods +description: Recommendations and considerations for determining the correct resource requests and limits for application pods in a Kubernetes system. +published: 2022-10-31 +id: TN0016 +tags: [router, kubernetes] +redirectFrom: + - /technotes/TN0016-router-resource-management/ +--- + + + +Self-hosting the GraphOS Router is limited to [GraphOS Enterprise plans](https://www.apollographql.com/pricing). Other plan types use [managed cloud routing with GraphOS](/graphos/cloud-routing). Check out the [pricing page](https://www.apollographql.com/pricing#graphos-router) to learn more. + + + +Determining the correct resource requests and limits for your application pods in a Kubernetes system is not an exact science. Your specific needs depend on many factors, including: + +- The cardinality of unique operation shapes +- The latency of underlying subgraphs and data sources +- The size of responses +- The complexity of query plans + +Our general recommendation for Kubernetes is to start with these requests and limits: + +```yaml +resources: + requests: + memory: '1G' + cpu: '1000m' + limits: + memory: '2G' + # no CPU limit to avoid throttling +``` + + + +The [router resource estimator](/graphos/routing/self-hosted/resource-estimator) is a helpful tool for getting a starting baseline for what resources you may need in production based on your expected traffic. + + + +When using [Horizontal pod autoscaling](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/), we recommend targeting 90% utilization: + +```yaml +metrics: + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: 90 + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: 90 +``` + +The GraphOS Router starts up quickly, but when connected to GraphOS the router has to fetch the supergraph schema from Apollo Uplink before it can start serving traffic. We recommend measuring your router's startup time and lowering the `averageUtilization` if your startup time is longer due to Uplink latency or the size of your supergraph schema.