diff --git a/docs/source/reference/upgrade/from-router-v1.mdx b/docs/source/reference/upgrade/from-router-v1.mdx
index 86ea2130c5..2b9c608170 100644
--- a/docs/source/reference/upgrade/from-router-v1.mdx
+++ b/docs/source/reference/upgrade/from-router-v1.mdx
@@ -4,115 +4,345 @@ subtitle: Upgrade from version 1.x to 2.x of GraphOS Router
description: Learn how to upgrade from version 1.x to 2.x of the GraphOS Router.
---
-Learn how to upgrade your GraphOS Router deployment from version 1.x to 2.x.
-
GraphOS Router 2.x is available as a [Developer Preview](https://www.apollographql.com/docs/graphos/reference/router-release-lifecycle#developer-preview). The most recent version is **{products.router.version("connectors").version}**. This upgrade guide will be updated throughout the Developer Preview and will have additions after each release.
-## New configuration in GraphOS Router v2.0.0-preview.x
+Router v2.x includes various breaking changes when upgrading from v1.x, including removing deprecated features and renaming public interfaces to be more future-proof.
-The router v2.x introduces some new features that can impact the configuration from v1.x.
+This upgrade guide describes the steps to upgrade your GraphOS Router deployment from version 1.x to 2.x. It describes breaking changes and how to resolve them. It also recommends new features to use.
-### Apollo operation usage reporting via OTLP
+## Upgrade strategy
-The router supports reporting operation usage metrics to GraphOS via OpenTelemetry Protocol (OTLP).
+Before making any changes, auto-upgrade your configuration. This will remove options that already have no effect in v1.x, and make the rest of the upgrade easier.
-Prior to version 1.49.0 of the router, all GraphOS reporting was performed using a [private tracing format](/graphos/metrics/sending-operation-metrics#reporting-format). In v1.49.0, we introduced support for using OTel to perform this reporting. In v1.x, this is controlled using the `experimental_otlp_tracing_sampler` flag, and it's off by default.
+Check the changes that will be applied using:
+```bash
+router config upgrade --diff router.yaml
+```
-Now in v2.x, this flag is renamed to `otlp_tracing_sampler`, and it's enabled by default.
+Then apply the changes using:
+```bah
+router config upgrade router.yaml > router.next.yaml
+mv router.next.yaml router.yaml
+```
-Learn more about configuring [usage reporting via OTLP](/router/configuration/telemetry/apollo-telemetry#usage-reporting-via-opentelemetry-protocol-otlp).
+## Removals and deprecations
-### Metrics reporting defaults
+The following headings describe features that have been removed or deprecated in router v2.x. Alternatives to the removed or deprecated features are described, if available.
-Default values of some GraphOS reporting metrics have been changed from v1.x to the following in v2.x:
+### Removed metrics
-- `telemetry.apollo.signature_normalization_algorithm` now defaults to `enhanced`. (In v1.x the default is `legacy`.)
-- `telemetry.apollo.metrics_reference_mode` now defaults to `extended`. (In v1.x the default is `standard`.)
+Multiple metrics have been removed in router v2.x as part of evolving towards OpenTelemetry metrics and conventions. Each of the removed metrics listed below has a replacement metric or a method for deriving its value:
+
+- `apollo_router_http_request_retry_total`. Use the `http.client.request.duration`
+ metric's `http.request.resend_count` attribute. Set [`default_requirement_level`](/docs/graphos/reference/router/telemetry/instrumentation/instruments#default_requirement_level)
+ to `recommended` to make the Router emit this attribute.
+
+- `apollo_router_timeout`. This metric conflated timed-out requests from client
+ to the router, and requests from the router to subgraphs. Timed-out requests
+ have HTTP status code 504. Use the `http.response.status_code` attribute on the
+ `http.server.request.duration` metric to identify timed-out router requests, and
+ the same attribute on the `http.client.request.duration` metric to identify
+ timed-out subgraph requests.
+
+- `apollo_router_http_requests_total`. This is replaced by
+ `http.server.request.duration` metric for requests from clients to router and
+ `http.client.request.duration` for requests from router to subgraphs.
+
+- `apollo_router_http_request_duration_seconds`. This is replaced by
+ `http.server.request.duration` metric for requests from clients to router and
+ `http.client.request.duration` for requests from router to subgraphs.
+
+- `apollo_router_session_count_total`. This is replaced by
+ `http.server.active_requests`.
+
+- `apollo_require_authentication_failure_count`. Use the
+ `http.server.request.duration` metric's `http.response.status_code` attribute.
+ Requests with authentication failures have HTTP status code 401.
+
+- `apollo_authentication_failure_count`. Use the
+ `apollo.router.operations.authentication.jwt` metric's
+ `authentication.jwt.failed` attribute.
+
+- `apollo_authentication_success_count`. Use the
+ `apollo.router.operations.authentication.jwt` metric instead. If the
+ `authentication.jwt.failed` attribute is _absent_ or `false`, the authentication
+ succeeded.
-## Removed features in GraphOS Router v2.x
+- `apollo_router_deduplicated_subscriptions_total`. Use the
+ `apollo.router.operations.subscriptions` metric's `subscriptions.deduplicated`
+ attribute.
+
+- `apollo_router_cache_miss_count`. Cache miss count can be derived from `apollo.router.cache.miss.time`.
+
+- `apollo_router_cache_hit_count`. Cache hit count can be derived from `apollo.router.cache.hit.time`.
+
+### Removed processing time metrics
+
+Calculating the overhead of injecting the router into your service stack when making multiple downstream calls is a complex task. Due to the router being unable to get reliable calculations, the metrics `apollo_router_span` and `apollo_router_processing_time` have been removed.
+
+**Upgrade step**: test your workloads with the router and validate that its latency meets your requirements.
+
+
+### Removed custom instrumentation selectors
+
+
+
+The `subgraph_response_body` selector is removed in favor of `subgraph_response_data` and `subgraph_response_errors`.
+
+**Upgrade step**: replace `subgraph_response_body` with `subgraph_response_data` and `subgraph_response_errors`. For example:
+
+```yaml
+telemetry:
+ instrumentation:
+ instruments:
+ subgraph:
+ http.client.request.duration:
+ attributes:
+ http.response.status_code:
+ subgraph_response_status: code
+ my_data_value:
+ # Previously:
+ # subgraph_response_body: .data.test
+ subgraph_response_data: $.test # The data object is the root object of this selector
+ my_error_code:
+ # Previously:
+ # subgraph_response_body: .errors[*].extensions.extra_code
+ subgraph_response_errors: $[*].extensions.extra_code # The errors object is the root object of this selector
+```
-### Support for Scaffold
+### Scaffold no longer supported for Rust plugin code generation
-In Router v1.x Scaffold could be used to generate boilerplate source code for a Rust Plugin which extended functionality in a custom Router. This facility has been removed.
+Support for Scaffold (todo: provide link) for generating boilerplate source code for a Rust plugin has been removed in router v2.x.
-Source code generated using Scaffold will continue to compile; so existing Rust plugins will be unaffected by this change.
+**Upgrade step**: Source code generated using Scaffold will continue to compile, so existing Rust plugins will be unaffected by this change.
-### `--apollo-uplink-poll-interval`
+### Removed configurable poll interval for Apollo Uplink
-The router no longer uses the `--apollo-uplink-poll-interval` command-line argument, or the `APOLLO_UPLINK_POLL_INTERVAL` environment variable. It already did something unusual in v1.x: the configured interval would only be used for the very first poll, and not any subsequent polls.
+The configurable poll interval of Apollo Uplink has been removed in router v2.x.
+
+**Upgrade step**: remove uses of both the `--apollo-uplink-poll-interval` command-line argument and the `APOLLO_UPLINK_POLL_INTERVAL` environment variable.
-### Hot reloading `--supergraph-urls`, `APOLLO_ROUTER_SUPERGRAPH_URLS`
+### Removed hot reloading of supergraph URLs
-The `--supergraph-urls` command-line argument or the `APOLLO_ROUTER_SUPERGRAPH_URLS` environment variable no longer support hot reloading. In v1.x, if hot reloading was enabled, the router would repeatedly fetch the URLs on the interval specified by `--apollo-uplink-poll-interval`.
+Hot reloading is no longer supported for supergraph URLs configured via either the `--supergraph-urls` command-line argument or the `APOLLO_ROUTER_SUPERGRAPH_URLS` environment variable. In router v1.x, if hot reloading was enabled, the router would repeatedly fetch the URLs on the interval specified by `--apollo-uplink-poll-interval`. This poll interval has been removed in v2.x.
-If hot reloading from a remote URL is desired, consider running a script to download the supergraph URL on an interval, and point the router to the downloaded file on the filesystem.
+**Upgrade step**: if you want to hot reload from a remote URL, try running a script that downloads the supergraph URL at a periodic interval, then point the router to the downloaded file on the filesystem.
-### `--schema`
+### Removed busy timer for request processing duration
-The deprecated `--schema` command-line argument is removed. `router config schema` should be used to print the configuration supergraph instead.
+In `context::Context` that's typically used for router customizations, methods and structs related to request processing duration have been removed, because request processing duration is already included as part of spans sent by the
+router. Users customizing the router with Rhai scripts, Rust scripts, or coprocessors don't need to track this information manually.
-### Busy timer for request processing duration
-Request processing duration is already included as part of the spans sent by the
-router, and there is no need for rust plugin, coprocessor and rhai plugin users
-to track this information manually. As a result, the following methods and structs were removed from `context::Context`:
+**Upgrade step**: remove calls and uses of the following methods and structs from `context::Context`:
- `context::Context::busy_time()`
- `context::Context::enter_active_request()`
- `context::BusyTimer` struct
- `context::BusyTimerGuard` struct
-### Deprecated methods in rust plugins
+### Removed `OneShotAsyncCheckpointLayer` and `.oneshot_checkpoint_async()`
+
+Both `OneShotAsyncCheckpointLayer` and `.oneshot_checkpoint_async() are removed as part of architectural optimizations in router v2.x.
+
+**Upgrade step**:
+- Replace uses of `apollo_router::layers::ServiceBuilderExt::oneshot_checkpoint_async` with the `checkpoint_async` method.
+
+- Replace uses of `OneShotAsyncCheckpointLayer` with `AsyncCheckpointLayer`. For example:
+
+Previous plugin code using `OneShotAsyncCheckpointLayer`:
+
+```rust
+OneShotAsyncCheckpointLayer::new(move |request: execution::Request| {
+ let request_config = request_config.clone();
+ // ...
+})
+.service(service)
+.boxed()
+```
+
+New plugin code using `AsyncCheckpointLayer`
+
+```rust
+use apollo_router::layers::async_checkpoint_layer::AsyncCheckpointLayer;
+
+AsyncCheckpointLayer::new(move |request: execution::Request| {
+ let request_config = request_config.clone();
+ // ...
+})
+.buffered()
+.service(service)
+.boxed()
+```
+
+
+
+The `buffered()` method is provided by the `apollo_router::layers::ServiceBuilderExt` trait and ensures that your service may be cloned.
+
+
+
-The following deprecated methods are removed from rust plugins' API:
+### Removed deprecated methods of Rust plugins
+
+The following deprecated methods are removed from the public crate API available to Rust plugins:
- `services::router::Response::map()`
-- `router::event::schema::SchemaSource::File.delay` field
-- `router::event::configuration::Configuration::File.delay` field
+- `SchemaSource::File.delay` field
+- `ConfigurationSource::File.delay` field
- `context::extensions::sync::ExtensionsMutex::lock()`. Use `ExtensionsMutex::with_lock()` instead.
- `test_harness::TestHarness::build()`. Use `TestHarness::build_supergraph()` instead.
- `PluginInit::new()`. Use `PluginInit::builder()` instead.
- `PluginInit::try_new()`. Use `PluginInit::try_builder()` instead.
-## Upgrading to GraphOS Router v2.x
+### Removed Jaeger tracing exporter
-Upgrading from GraphOS Router v1.x to v2.x requires the following steps.
+The `jaeger` exporter has been removed, as Jaeger now fully supports the OTLP format.
-### Configure your Apollo usage reporting protocol
+**Upgrade step**:
-If your router v1.x is configured with `experimental_otlp_tracing_sampler`, rename it to `otlp_tracing_sampler`.
+- Change your router config to use the `otlp` exporter:
-To [report operation usage metrics to GraphOS via OTLP](#apollo-operation-usage-reporting-via-otlp), you can either remove your configuration of `otlp_tracing_sampler` and use its default value, or you can explicitly enable it by setting it to [`always_on` or a sampling ratio](/router/configuration/telemetry/apollo-telemetry#configuring-usage-reporting-via-otlp).
+```yaml title="router.yaml"
+telemetry:
+ exporters:
+ tracing:
+ propagation:
+ jaeger: true
+ otlp:
+ enabled: true
+```
-Otherwise, to use the behavior of v1.x, turn off usage reporting via OTLP by setting `otlp_tracing_sampler` to `always_off`.
+- Ensure that you have enabled OTLP support in your Jaeger instance using `COLLECTOR_OTLP_ENABLED=true` and exposing ports `4317` and `4318` for gRPC and HTTP, respectively.
-### Configure metrics reporting defaults
+### Emitting custom metrics
-If you plan to use the [new metrics reporting defaults](#metrics-reporting-defaults), then no changes are required.
+Rust plugins can no longer use the router's internal metrics system via `tracing` macros. Consequently, `tracing` field names that start with the following strings aren't interpreted as macros for router metrics:
+- `counter.`
+- `histogram.`
+- `monotonic_counter.`
+- `value.`
-Otherwise, to use the defaults from v1.x, set the following:
+**Upgrade step**: instead of using `tracing` macros , use [OpenTelemetry](https://docs.rs/opentelemetry/latest/opentelemetry/) crates. You can use the new `apollo_router::metrics::meter_provider()` API to access the router's global meter provider to register your instruments.
-```yaml
-telemetry:
- apollo:
- signature_normalization_algorithm: legacy
- metrics_reference_mode: standard
-```
+
-### Configure supergraph endpoint path
+The router v2.x logs an error for each legacy metric field it detects in a `tracing` event.
-If you use the default endpoint path or your path has no matched parameters or wildcards, then no changes are required.
+
+
+### Removed `--schema` CLI argument
+
+The deprecated `--schema` command-line argument is removed in router v2.x
+
+**Upgrade step**: replace uses of `--schema` with `router config schema` to print the configuration supergraph.
+
+
+## Configuration changes
-If your path uses named parameters, it is now bound with a braces syntax instead of a colon:
+The following describes changes to router configuration, including renamed options and changed default values.
+
+### Renamed metrics
+
+Various metrics in router 2.x have been renamed to conform to the OpenTelemetry convention of using `.` as the namespace separator, instead of `_`.
+
+**Update step**: use the updated names for the following metrics:
+
+| Previous metric | Renamed metric |
+| --------------- | -------------- |
+| `apollo_router_opened_subscriptions` | `apollo.router.opened.subscriptions` |
+| `apollo_router_cache_hit_time` | `apollo.router.cache.hit.time` |
+| `apollo_router_cache_size` | `apollo.router.cache.size` |
+| `apollo_router_cache_miss_time` | `apollo.router.cache.miss.time` |
+| `apollo_router_state_change_total` | `apollo.router.state.change.total` |
+| `apollo_router_span_lru_size` | `apollo.router.exporter.span.lru.size` * |
+| `apollo_router_session_count_active` | `apollo.router.session.count.active` |
+| `apollo_router_uplink_fetch_count_total` | `apollo.router.uplink.fetch.count.total` |
+| `apollo_router_uplink_fetch_duration_seconds` | `apollo.router.uplink.fetch.duration.seconds`|
+
+
+
+\* `apollo.router.exporter.span.lru.size` now also has an additional `exporter` prefix.
+
+
+
+### Changed trace default
+
+In router v2.x, the trace [`telemetry.instrumentation.spans.mode`](/graphos/reference/router/telemetry/instrumentation/spans#mode) has a default value of `spec_compliant`. Previously in router 1.x, its default value was `deprecated`.
+
+### Changed defaults of GraphOS reporting metrics
+
+Default values of some GraphOS reporting metrics have been changed from v1.x to the following in v2.x:
+
+- `telemetry.apollo.signature_normalization_algorithm` now defaults to `enhanced`. (In v1.x the default is `legacy`.)
+- `telemetry.apollo.metrics_reference_mode` now defaults to `extended`. (In v1.x the default is `standard`.)
+
+
+### Renamed configuration for Apollo operation usage reporting via OTLP
+
+The router supports reporting operation usage metrics to GraphOS via OpenTelemetry Protocol (OTLP).
+
+Prior to version 1.49.0 of the router, all GraphOS reporting was performed using a [private tracing format](/graphos/metrics/sending-operation-metrics#reporting-format). In v1.49.0, we introduced support for using OTel to perform this reporting. In v1.x, this is controlled using the `experimental_otlp_tracing_sampler` flag, and it's off by default.
+
+Now in v2.x, this flag is renamed to `otlp_tracing_sampler`, and it's enabled by default.
+
+**Upgrade step**: in your router config, replace uses of `experimental_otlp_tracing_sampler` to `otlp_tracing_sampler`.
+
+Learn more about configuring [usage reporting via OTLP](/router/configuration/telemetry/apollo-telemetry#usage-reporting-via-opentelemetry-protocol-otlp).
+
+### Renamed context keys
+
+The router request context is used to share data across stages of the request pipeline. The keys have been renamed to prevent conflicts and to better indicate which pipeline stage or plugin populates the data.
+
+
+
+You can continue using deprecated context key names from router 1.x if you configure `context: deprecated` in your router. For details, see [Context configuration](/graphos/routing/customization/coprocessor#context-configuration).
+
+
+
+**Upgrade step**: if you access context entries in a custom plugin, Rhai script, coprocessor, or telemetry selector, you can update your context keys to account for the new names:
+
+| Previous context key name | New context key name |
+| ------------------------- | -------------------- |
+| `apollo_authentication::JWT::claims` | `apollo::authentication::jwt_claims` |
+| `apollo_authorization::authenticated::required` | `apollo::authorization::authentication_required` |
+| `apollo_authorization::scopes::required` | `apollo::authorization::required_scopes` |
+| `apollo_authorization::policies::required` | `apollo::authorization::required_policies` |
+| `apollo_operation_id` | `apollo::supergraph::operation_id` |
+| `apollo_override::unresolved_labels` | `apollo::progressive_override::unresolved_labels` |
+| `apollo_override::labels_to_override` | `apollo::progressive_override::labels_to_override` |
+| `apollo_router::supergraph::first_event` | `apollo::supergraph::first_event` |
+| `apollo_telemetry::client_name` | `apollo::telemetry::client_name` |
+| `apollo_telemetry::client_version` | `apollo::telemetry::client_version` |
+| `apollo_telemetry::studio::exclude` | `apollo::telemetry::studio_exclude` |
+| `apollo_telemetry::subgraph_ftv1` | `apollo::telemetry::subgraph_ftv1` |
+| `cost.actual` | `apollo::demand_control::actual_cost` |
+| `cost.estimated` | `apollo::demand_control::estimated_cost` |
+| `cost.result` | `apollo::demand_control::result` |
+| `cost.strategy` | `apollo::demand_control::strategy` |
+| `experimental::expose_query_plan.enabled` | `apollo::expose_query_plan::enabled` |
+| `experimental::expose_query_plan.formatted_plan` | `apollo::expose_query_plan::formatted_plan` |
+| `experimental::expose_query_plan.plan` | `apollo::expose_query_plan::plan` |
+| `operation_kind` | `apollo::supergraph::operation_kind` |
+| `operation_name` | `apollo::supergraph::operation_name` |
+| `persisted_query_hit` | `apollo::apq::cache_hit` |
+| `persisted_query_register` | `apollo::apq::registered` |
+
+
+
+### Updated syntax for configuring supergraph endpoint path
+
+The syntax for configuring the router to receive GraphQL requests at a specific URL path has been updated:
+
+- The syntax for named parameters was changed from a colon to braces:
```yaml
supergraph:
@@ -121,7 +351,7 @@ supergraph:
path: /foo/{bar}/baz
```
-If your path uses a wildcard, it must be wrapped in braces and must bind a name:
+- The syntax for wildcards was changed to require braces and a name:
```yaml
supergraph:
@@ -130,25 +360,63 @@ supergraph:
path: /foo/{*rest}
```
-### Logging
+
+
+No syntax changes are required when using the default endpoint path or a path without wildcards.
+
+
+
+### Changed syntax for header propagation path
+
+
+
+In router v2.x, the path used for selecting data from a client request body for [header propagation](/docs/graphos/routing/header-propagation#insert) must comply with the [JSONPath](https://www.ietf.org/archive/id/draft-goessner-dispatch-jsonpath-00.html) spec. This means a `$` is now required to select the root element.
+
+**Upgrade step**: in your router config, prefix your paths with a `$` when selecting root elements. For example:
+
+```yaml
+headers:
+ all:
+ request:
+ - insert:
+ name: from_app_name
+ # Previously:
+ # path: .extensions.metadata[0].app_name
+ path: $.extensions.metadata[0].app_name
+```
+
+## Functionality changes
+
+### Updated `tower` service pipeline
+
+In router v1.x, a brand new `tower::Service` pipeline was built for every request, so Rust plugin hooks were called for every request. Now in router v2.x, the `tower::Service` pipeline is built once and cloned for every request.
+
+**Upgrade step**: carefully audit how your Rust plugins store state in any `tower` services you add to the pipeline, because the `tower` service is now cloned for every request.
+
+
+## New capabilities
+
+The following lists new capabilities in router v2.x that we recommend you use. These capabilities don't introduce breaking changes.
+
+### More granular logging with custom telemetry
-If you used the `experimental_when_header` feature previously like this for example:
+Previously, router v1.x had an experimental `experimental_when_header` feature to log requests and responses if a request header was set to a specific value. This feature provided very limited control:
```yaml title="router.previous.yaml"
telemetry:
exporters:
logging:
# If one of these headers matches we will log supergraph and subgraphs requests/responses
- experimental_when_header: # REMOVED
+ experimental_when_header: # NO LONGER SUPPORTED
- name: apollo-router-log-request
value: my_client
headers: true # default: false
body: true # default: false
```
-This feature no longer exists and can be replaced with another one included in custom telemetry. Here is how you would configure custom telemetry to achieve the same result:
+In router v2.x, you can achieve much more granular logging using custom telemetry. The example below logs requests and responses at every stage of the request pipeline:
```yaml title="router.yaml"
telemetry:
@@ -195,271 +463,78 @@ telemetry:
- my_client
```
-### Introspection depth limit
-
-The [schema-intropsection schema](https://spec.graphql.org/draft/#sec-Schema-Introspection.Schema-Introspection-Schema) is recursive: a client can query the fields of the types of some other fields, and so on arbitrarily deep. This can produce responses that grow much faster than the size of the request.
-
-To protect against abusive requests Router now refuses to execute introspection queries that nest list fields too deep and returns an error instead. The criteria matches `MaxIntrospectionDepthRule` in graphql-js, but may change in future versions.
-
-In case it rejects legitimate queries, this check can be disabled in Router configuration:
-
-```yaml
-# Do not enable introspection in production!
-supergraph:
- introspection: true # Without this, schema introspection is entirely disabled by default
-limits:
- introspection_max_depth: false # Defaults to true
-```
-
-### Traces
-
-- `telemetry.instrumentation.spans.mode` becomes `spec_compliant` by default instead of `deprecated`.
-
-### Renamed Metrics
-
-Some of the older metrics in the router were not using the most recent `.` naming convention and were instead separated by `_`. For consistency purposes, the following metrics are renamed:
-
-| Previous metric | Renamed metric |
-| --------------- | -------------- |
-| `apollo_router_opened_subscriptions` | `apollo.router.opened.subscriptions` |
-| `apollo_router_cache_hit_time` | `apollo.router.cache.hit.time` |
-| `apollo_router_cache_size` | `apollo.router.cache.size` |
-| `apollo_router_cache_miss_time` | `apollo.router.cache.miss.time` |
-| `apollo_router_state_change_total` | `apollo.router.state.change.total` |
-| `apollo_router_span_lru_size` | `apollo.router.exporter.span.lru.size` $_{[1]} |
-| `apollo_router_session_count_active` | `apollo.router.session.count.active` |
-| `apollo_router_uplink_fetch_count_total` | `apollo.router.uplink.fetch.count.total` |
-| `apollo_router_uplink_fetch_duration_seconds` | `apollo.router.uplink.fetch.duration.seconds`|
-
-$_{[1]} `apollo.router.exporter.span.lru.size` now also has an additional `exporter` prefix.
-
-### Removed metrics
-
-The following metrics have been removed:
-
-- `apollo_router_http_request_retry_total`. This will be supported now by `http.client.request.duration` metrics
- with the `http.request.resend_count` attribute which is automatically set when `default_requirement_level` is set to `recommended`.
-
-- `apollo_router_timeout`. This metric conflated timed-out requests from client
- to the router, and requests from the router to subgraphs. Timed-out requests
- have HTTP status code 504. Use the `http.response.status_code` attribute on the
- `http.server.request.duration` metric to identify timed-out router requests, and
- the same attribute on the `http.client.request.duration` metric to identify
- timed-out subgraph requests.
-
-- `apollo_router_http_requests_total`. This is replaced by
- `http.server.request.duration` metric for requests from clients to router and
- `http.client.request.duration` for requests from router to subgraphs.
-
-- `apollo_router_http_request_duration_seconds_bucket`. This is replaced by
- `http.server.request.duration` metric for requests from clients to router and
- `http.client.request.duration` for requests from router to subgraphs.
-
-- `apollo_router_session_count_total`. This is replaced by
- `http.server.active_requests`.
-
-- `apollo_require_authentication_failure_count`. Use the
- `http.server.request.duration` metric's `http.response.status_code` attribute.
- Requests with authentication failures have HTTP status code 401.
+### Improved traffic shaping
-- `apollo_authentication_failure_count`. Use the
- `apollo.router.operations.authentication.jwt` metric's
- `authentication.jwt.failed` attribute.
-
-- `apollo_authentication_success_count`. Use the
- `apollo.router.operations.authentication.jwt` metric instead. If the
- `authentication.jwt.failed` attribute is _absent_ or `false`, the authentication
- succeeded.
-
-- `apollo_router_deduplicated_subscriptions_total`. Use the
- `apollo.router.operations.subscriptions` metric's `subscriptions.deduplicated`
- attribute
-
-- `apollo_router_cache_miss_count`. Cache miss count can be derived from `apollo.router.cache.miss.time.count`.
-
-- `apollo_router_cache_hit_count`. Cache hit count can be derived from `apollo.router.cache.hit.time.count`.
-
-- Calculating the overhead of injecting the router into your service stack when
- making multiple downstream calls is a complex task. With that, we are removing
- the following two misleading metrics and recommending that you instead test your
- workloads with the router to if the latency meets your requirements:
- - `apollo_router_span`
- - `apollo_router_processing_time`
-
-
+
-- If you used the `subgraph_response_body` selector for telemetry like this:
+Traffic shaping has been improved significantly in router v2.x. We've added a new mechanism, concurrency control, and we've improved the router's ability to observe timeout and traffic shaping restrictions correctly. These improvements do mean that clients of the router may see an increase in:
-```yaml
-telemetry:
- instrumentation:
- instruments:
- subgraph:
- http.client.request.duration:
- attributes:
- http.response.status_code:
- subgraph_response_status: code
- my_data_value:
- subgraph_response_body: .data.test
-```
-
-You'll have to migrate the `subgraph_response_body` to `subgraph_response_data` selector (or `subgraph_response_errors` if you want to target errors):
+- [Service Unavailable](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503)
+- [Gateway Timeout](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504)
-```yaml
-telemetry:
- instrumentation:
- instruments:
- subgraph:
- http.client.request.duration:
- attributes:
- http.response.status_code:
- subgraph_response_status: code
- my_data_value:
- subgraph_response_data: $.test # Heads up, we removed the .data prefix as it's directly targeting data and we added $
-```
+errors as traffic shaping constraints are enforced.
-### Context Keys
-
-The router request context is used to share data across stages of the request pipeline. The keys have been renamed for consistency and to better indicate which pipeline stage or plugin populates the data. If you access context entries in a custom plugin, Rhai script, coprocessor, or telemetry selector, update your context keys to account for the new names:
-
-- `apollo_authentication::JWT::claims` -> `apollo::authentication::jwt_claims`
-- `apollo_authorization::authenticated::required` -> `apollo::authorization::authentication_required`
-- `apollo_authorization::scopes::required` -> `apollo::authorization::required_scopes`
-- `apollo_authorization::policies::required` -> `apollo::authorization::required_policies`
-- `apollo_operation_id` -> `apollo::supergraph::operation_id`
-- `apollo_override::unresolved_labels` -> `apollo::progressive_override::unresolved_labels`
-- `apollo_override::labels_to_override` -> `apollo::progressive_override::labels_to_override`
-- `apollo_router::supergraph::first_event` -> `apollo::supergraph::first_event`
-- `apollo_telemetry::client_name` -> `apollo::telemetry::client_name`
-- `apollo_telemetry::client_version` -> `apollo::telemetry::client_version`
-- `apollo_telemetry::studio::exclude` -> `apollo::telemetry::studio_exclude`
-- `apollo_telemetry::subgraph_ftv1` -> `apollo::telemetry::subgraph_ftv1`
-- `cost.actual` -> `apollo::demand_control::actual_cost`
-- `cost.estimated` -> `apollo::demand_control::estimated_cost`
-- `cost.result` -> `apollo::demand_control::result`
-- `cost.strategy` -> `apollo::demand_control::strategy`
-- `experimental::expose_query_plan.enabled` -> `apollo::expose_query_plan::enabled`
-- `experimental::expose_query_plan.formatted_plan` -> `apollo::expose_query_plan::formatted_plan`
-- `experimental::expose_query_plan.plan` -> `apollo::expose_query_plan::plan`
-- `operation_kind` -> `apollo::supergraph::operation_kind`
-- `operation_name` -> `apollo::supergraph::operation_name`
-- `persisted_query_hit` -> `apollo::apq::cache_hit`
-- `persisted_query_register` -> `apollo::apq::registered`
-
-### Tracing
-
-`jaeger` exporter has been removed as Jaeger fully supports to OTLP format. To use the `otlp` exporter change your router config:
+We recommend that users experiment with their configuration in order to arrive at the right combination of timeout, concurrency and rate limit controls for their particular use case.
-```yaml title="router.yaml"
-telemetry:
- exporters:
- tracing:
- propagation:
- jaeger: true
- otlp:
- enabled: true
-```
+For more information about [configuring traffic shaping](../../routing/performance/traffic-shaping.mdx).
-And ensure that you have enabled OTLP support in your Jaeger instance using `COLLECTOR_OTLP_ENABLED=true` and exposing ports `4317` and or `4318` for gRPC and HTTP respectively.
+### Enforce introspection depth limit
-### Check CORS configuration
+To protect against abusive requests, the router enforces a depth limit on introspection queries by default.
-If you already configured [CORS](../../routing/security/cors) on the router, the configuration won't change but with v1.x it accepted bad configuration and displayed an error log when some header names or regexes were invalid.
-With v2.x it will end up with an error and it won't start at all to avoid confusions and misconfigurations.
+Because the [schema-introspection schema](https://spec.graphql.org/draft/#sec-Schema-Introspection.Schema-Introspection-Schema) is recursive, a client can query fields of the types of some other fields at unbounded nesting levels, and this can produce responses that grow much faster than the size of the request. Consequently, the router by default refuses to execute introspection queries that nest list fields too deep and instead returns an error.
-### Headers propagation
+
-
+- The criteria matches `MaxIntrospectionDepthRule` in graphql-js, but may change in future versions.
-If you use the ability to get data from request body and insert this data in a subgraph request header, we updated the `path` field type to be [JSONPath](https://www.ietf.org/archive/id/draft-goessner-dispatch-jsonpath-00.html) compliant
-So if you had this configuration for example:
+- In rare cases where the router rejects legitimate queries, you can configure the router to disable the limit by setting `limits.introspection_max_depth: false`. For example:
```yaml
-headers:
- all:
- request:
- - insert:
- name: from_app_name
- path: .extensions.metadata[0].app_name
+# Do not enable introspection in production!
+supergraph:
+ introspection: true # Without this, schema introspection is entirely disabled by default
+limits:
+ introspection_max_depth: false # Defaults to true
```
-You'll have to migrate the `path` field to be JSONPath compliant and just add `$` at the beginning of the `path`, example:
-
-```yaml
-headers:
- all:
- request:
- - insert:
- name: from_app_name
- path: $.extensions.metadata[0].app_name
-```
+
-### OneShotAsyncCheckpoint
+### Enforce valid CORS configuration
-This has been removed because it is incompatible with the architectural optimizations we've made in Router 2.0. If you were using this in a Rust Plugin, you can replace it easily with `AsyncCheckpoint` as follows:
+Previously in router v1.x, invalid values in the CORS configuration, such as malformed regexes, were ignored with an error logged.
-Plugin code using `OneShotAsyncCheckpoint`
+Now in router 2.x, such invalid values in the CORS configuration prevent the router from starting up and result in errors like the following:
```
- OneShotAsyncCheckpointLayer::new(move |request: execution::Request| {
- let request_config = request_config.clone();
-
- }
- .service(service)
- .boxed()
+could not create router: CORS configuration error:
```
-Replace with `AsyncCheckpoint`
+**Upgrade step****: Validate your CORS configuration. For details, go to [CORS configuration documentation](/graphos/routing/security/cors).
-```
- AsyncCheckpointLayer::new(move |request: execution::Request| {
- let request_config = request_config.clone();
-
- }
- .buffered()
- .service(service)
- .boxed()
-```
+
+Unsorted items (TODO)
-The `buffered()` method is provided by the `apollo_router::layers::ServiceBuilderExt` trait and ensures that you service may be cloned.
+## TBD
-
+### Default Apollo usage reporting protocol
+
-### Traffic Shaping
-
-Traffic shaping has been improved significantly in Router 2.0. We've added a new mechanism, concurrency control, and we've improved the router's ability to observe timeout and traffic shaping restrictions correctly. These improvements do mean that clients of the router may see an increase in:
-
-- [Service Unavailable](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/503)
-- [Gateway Timeout](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/504)
-
-errors as traffic shaping constraints are enforced.
-
-We recommend that users experiment with their configuration in order to arrive at the right combination of timeout, concurrency and rate limit controls for their particular use case.
-
-For more information about [configuring traffic shaping](../../routing/performance/traffic-shaping.mdx).
-
-
-
-### Subgraph Request/Response
+If your router v1.x is configured with `experimental_otlp_tracing_sampler`, rename it to `otlp_tracing_sampler`.
-If, in your Rust plugin, you were using either the subgraph::Request::subgraph_name or the subgraph::Response::subgraph_name, please note that these are no longer `Option`, but are mandatory.
+To [report operation usage metrics to GraphOS via OTLP](#apollo-operation-usage-reporting-via-otlp), you can either remove your configuration of `otlp_tracing_sampler` and use its default value, or you can explicitly enable it by setting it to [`always_on` or a sampling ratio](/router/configuration/telemetry/apollo-telemetry#configuring-usage-reporting-via-otlp).
-### Emitting metrics in Rust plugins
+Otherwise, to use the behavior of v1.x, turn off usage reporting via OTLP by setting `otlp_tracing_sampler` to `always_off`.
-Previously, Rust plugins could use the Router's internal metrics system using the `tracing` macros. This is no longer supported, and the opentelemetry crates should be used instead.
+
-`tracing` field names starting with these strings are no longer treated specially:
-- `counter.`
-- `histogram.`
-- `monotonic_counter.`
-- `value.`
+
-Instead, use the [OpenTelemetry](https://docs.rs/opentelemetry/latest/opentelemetry/) crates.
-You can use the new `apollo_router::metrics::meter_provider()` API to access the router's global meter provider to register your instruments.
+
-### Deploy your router
+## Deploy your router
-Make sure that you are referencing the correct router release: **{products.router.version("connectors").version}**
+Make sure that you are referencing the correct router release: **v{products.router.version("connectors").version}**
During upgrade, carefully monitor logs and resource consumption to ensure that your router has successfully upgraded and that your router has enough resources to perform as expected. The router will automatically migrate required configuration changes, but it is good practice to review the steps above and decide if you want to change your configuration.
@@ -467,4 +542,4 @@ For example, you may decide that you wish to change the way in which you sample
## Reporting upgrade issues
-If you encounter an upgrade issue that isn't resolved by this article, please search for existing [GitHub discussions](https://github.com/apollographql/router/discussions/) and start a new discussion if you don't find what you're looking for.
+If you encounter an upgrade issue that isn't resolved by this article, please search for existing [Apollo Community posts](https://community.apollographql.com/c/router/20) and start a new post if you don't find what you're looking for.