diff --git a/.changesets/fix_bryn_datadog_agent_sampling.md b/.changesets/fix_bryn_datadog_agent_sampling.md deleted file mode 100644 index 50c2d6997d..0000000000 --- a/.changesets/fix_bryn_datadog_agent_sampling.md +++ /dev/null @@ -1,34 +0,0 @@ -### Enable accurate Datadog APM metrics ([PR #6017](https://github.com/apollographql/router/pull/6017)) - -The router supports a new preview feature, the `preview_datadog_agent_sampling` option, to enable sending all spans to the Datadog Agent so APM metrics and views are accurate. - -Previously, the sampler option in `telemetry.exporters.tracing.common.sampler` wasn't Datadog-aware. To get accurate Datadog APM metrics, all spans must be sent to the Datadog Agent with a `psr` or `sampling.priority` attribute set appropriately to record the sampling decision. - -The `preview_datadog_agent_sampling` option enables accurate Datadog APM metrics. It should be used when exporting to the Datadog Agent, via OTLP or Datadog-native. - -```yaml -telemetry: - exporters: - tracing: - common: - # Only 10 percent of spans will be forwarded from the Datadog agent to Datadog. Experiment to find a value that is good for you! - sampler: 0.1 - # Send all spans to the Datadog agent. - preview_datadog_agent_sampling: true - - -``` - -Using these options can decrease your Datadog bill, because you will be sending only a percentage of spans from the Datadog Agent to Datadog. - -> [!IMPORTANT] -> Users must enable `preview_datadog_agent_sampling` to get accurate APM metrics. Users that have been using recent versions of the router will have to modify their configuration to retain full APM metrics. - -> [!IMPORTANT] -> The router doesn't support [`in-agent` ingestion control](https://docs.datadoghq.com/tracing/trace_pipeline/ingestion_mechanisms/?tab=java#in-the-agent). -> Configuring `traces_per_second` in the Datadog Agent won't dynamically adjust the router's sampling rate to meet the target rate. - -> [!IMPORTANT] -> Sending all spans to the Datadog Agent may require that you tweak the `batch_processor` settings in your exporter config. This applies to both OTLP and Datadog native exporters. - -Learn more by reading the [updated Datadog tracing documentation](https://apollographql.com/docs/router/configuration/telemetry/exporters/tracing/datadog) for more information on configuration options and their implications. \ No newline at end of file diff --git a/.changesets/fix_bryn_datadog_upstream_sampling_decision_propagation.md b/.changesets/fix_bryn_datadog_upstream_sampling_decision_propagation.md deleted file mode 100644 index d05f173528..0000000000 --- a/.changesets/fix_bryn_datadog_upstream_sampling_decision_propagation.md +++ /dev/null @@ -1,6 +0,0 @@ -### Fix transmitted header value for Datadog priority sampling resolution ([PR #6017](https://github.com/apollographql/router/pull/6017)) - -The router now transmits correct values of `x-datadog-sampling-priority` to downstream services. - -Previously, an `x-datadog-sampling-priority` of `-1` was incorrectly converted to `0` for downstream requests, and `2` was incorrectly converted to `1`. When propagating to downstream services, this resulted in values of `USER_REJECT` being incorrectly transmitted as `AUTO_REJECT`. - diff --git a/.changesets/fix_bryn_parent_based_sampling_fix_with_fix.md b/.changesets/fix_bryn_parent_based_sampling_fix_with_fix.md deleted file mode 100644 index 0e4dd64f96..0000000000 --- a/.changesets/fix_bryn_parent_based_sampling_fix_with_fix.md +++ /dev/null @@ -1,18 +0,0 @@ -### Fix non-parent sampling ([PR #6481](https://github.com/apollographql/router/pull/6481)) - -When the user specifies a non-parent sampler the router should ignore the information from upstream and use its own sampling rate. - -The following configuration would not work correctly: - -``` - exporters: - tracing: - common: - service_name: router - sampler: 0.00001 - parent_based_sampler: false -``` -All spans are being sampled. -This is now fixed and the router will correctly ignore any upstream sampling decision. - -By [@BrynCooke](https://github.com/BrynCooke) in https://github.com/apollographql/router/pull/6481 diff --git a/.changesets/fix_tninesling_subscription_operation_init.md b/.changesets/fix_tninesling_subscription_operation_init.md new file mode 100644 index 0000000000..9a41d1e894 --- /dev/null +++ b/.changesets/fix_tninesling_subscription_operation_init.md @@ -0,0 +1,5 @@ +### Eagerly init subgraph operation for subscription primary nodes ([PR #6509](https://github.com/apollographql/router/pull/6509)) + +When subgraph operations are deserialized, typically from a query plan cache, they are not automatically parsed into a full document. Instead, each node needs to initialize its operation(s) prior to execution. With this change, the primary node inside SubscriptionNode is initialized in the same way as other nodes in the plan. + +By [@tninesling](https://github.com/tninesling) in https://github.com/apollographql/router/pull/6509 diff --git a/CHANGELOG.md b/CHANGELOG.md index 39162412b6..3c0e4a4608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,64 @@ All notable changes to Router will be documented in this file. This project adheres to [Semantic Versioning v2.0.0](https://semver.org/spec/v2.0.0.html). +# [1.59.1] - 2025-01-08 + +## 🐛 Fixes + +### Fix transmitted header value for Datadog priority sampling resolution ([PR #6017](https://github.com/apollographql/router/pull/6017)) + +The router now transmits correct values of `x-datadog-sampling-priority` to downstream services. + +Previously, an `x-datadog-sampling-priority` of `-1` was incorrectly converted to `0` for downstream requests, and `2` was incorrectly converted to `1`. When propagating to downstream services, this resulted in values of `USER_REJECT` being incorrectly transmitted as `AUTO_REJECT`. + +### Enable accurate Datadog APM metrics ([PR #6017](https://github.com/apollographql/router/pull/6017)) + +The router supports a new preview feature, the `preview_datadog_agent_sampling` option, to enable sending all spans to the Datadog Agent so APM metrics and views are accurate. + +Previously, the sampler option in `telemetry.exporters.tracing.common.sampler` wasn't Datadog-aware. To get accurate Datadog APM metrics, all spans must be sent to the Datadog Agent with a `psr` or `sampling.priority` attribute set appropriately to record the sampling decision. + +The `preview_datadog_agent_sampling` option enables accurate Datadog APM metrics. It should be used when exporting to the Datadog Agent, via OTLP or Datadog-native. + +```yaml +telemetry: + exporters: + tracing: + common: + # Only 10 percent of spans will be forwarded from the Datadog agent to Datadog. Experiment to find a value that is good for you! + sampler: 0.1 + # Send all spans to the Datadog agent. + preview_datadog_agent_sampling: true +``` + +Using these options can decrease your Datadog bill, because you will be sending only a percentage of spans from the Datadog Agent to Datadog. + +> [!IMPORTANT] +> - Users must enable `preview_datadog_agent_sampling` to get accurate APM metrics. Users that have been using recent versions of the router will have to modify their configuration to retain full APM metrics. +> - The router doesn't support [`in-agent` ingestion control](https://docs.datadoghq.com/tracing/trace_pipeline/ingestion_mechanisms/?tab=java#in-the-agent). +> - Configuring `traces_per_second` in the Datadog Agent won't dynamically adjust the router's sampling rate to meet the target rate. +> - Sending all spans to the Datadog Agent may require that you tweak the `batch_processor` settings in your exporter config. This applies to both OTLP and Datadog native exporters. + +Learn more by reading the [updated Datadog tracing documentation](https://apollographql.com/docs/router/configuration/telemetry/exporters/tracing/datadog) for more information on configuration options and their implications. + +### Fix non-parent sampling ([PR #6481](https://github.com/apollographql/router/pull/6481)) + +When the user specifies a non-parent sampler the router should ignore the information from upstream and use its own sampling rate. + +The following configuration would not work correctly: + +``` + exporters: + tracing: + common: + service_name: router + sampler: 0.00001 + parent_based_sampler: false +``` +All spans are being sampled. +This is now fixed and the router will correctly ignore any upstream sampling decision. + +By [@BrynCooke](https://github.com/BrynCooke) in https://github.com/apollographql/router/pull/6481 + # [1.59.0] - 2024-12-17 > [!IMPORTANT] diff --git a/Cargo.lock b/Cargo.lock index 8325e314b1..e55d81f838 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -204,7 +204,7 @@ dependencies = [ [[package]] name = "apollo-federation" -version = "1.59.0" +version = "1.59.1" dependencies = [ "apollo-compiler", "derive_more", @@ -256,7 +256,7 @@ dependencies = [ [[package]] name = "apollo-router" -version = "1.59.0" +version = "1.59.1" dependencies = [ "access-json", "ahash", @@ -423,7 +423,7 @@ dependencies = [ [[package]] name = "apollo-router-benchmarks" -version = "1.59.0" +version = "1.59.1" dependencies = [ "apollo-parser", "apollo-router", @@ -439,7 +439,7 @@ dependencies = [ [[package]] name = "apollo-router-scaffold" -version = "1.59.0" +version = "1.59.1" dependencies = [ "anyhow", "cargo-scaffold", @@ -854,9 +854,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.84" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1244b10dcd56c92219da4e14caa97e312079e185f04ba3eea25061561dc0a0" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", diff --git a/apollo-federation/Cargo.toml b/apollo-federation/Cargo.toml index 222958209a..58dada163f 100644 --- a/apollo-federation/Cargo.toml +++ b/apollo-federation/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "apollo-federation" -version = "1.59.0" +version = "1.59.1" authors = ["The Apollo GraphQL Contributors"] edition = "2021" description = "Apollo Federation" diff --git a/apollo-router-benchmarks/Cargo.toml b/apollo-router-benchmarks/Cargo.toml index 53757506a1..d1e21f2b36 100644 --- a/apollo-router-benchmarks/Cargo.toml +++ b/apollo-router-benchmarks/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "apollo-router-benchmarks" -version = "1.59.0" +version = "1.59.1" authors = ["Apollo Graph, Inc. "] edition = "2021" license = "Elastic-2.0" diff --git a/apollo-router-scaffold/Cargo.toml b/apollo-router-scaffold/Cargo.toml index 3ce55f07d0..d4a57baa5e 100644 --- a/apollo-router-scaffold/Cargo.toml +++ b/apollo-router-scaffold/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "apollo-router-scaffold" -version = "1.59.0" +version = "1.59.1" authors = ["Apollo Graph, Inc. "] edition = "2021" license = "Elastic-2.0" diff --git a/apollo-router-scaffold/templates/base/Cargo.template.toml b/apollo-router-scaffold/templates/base/Cargo.template.toml index 7e188815b2..6a203b1a17 100644 --- a/apollo-router-scaffold/templates/base/Cargo.template.toml +++ b/apollo-router-scaffold/templates/base/Cargo.template.toml @@ -22,7 +22,7 @@ apollo-router = { path ="{{integration_test}}apollo-router" } apollo-router = { git="https://github.com/apollographql/router.git", branch="{{branch}}" } {{else}} # Note if you update these dependencies then also update xtask/Cargo.toml -apollo-router = "1.59.0" +apollo-router = "1.59.1" {{/if}} {{/if}} async-trait = "0.1.52" diff --git a/apollo-router-scaffold/templates/base/xtask/Cargo.template.toml b/apollo-router-scaffold/templates/base/xtask/Cargo.template.toml index 59e99a9f2e..e54f595298 100644 --- a/apollo-router-scaffold/templates/base/xtask/Cargo.template.toml +++ b/apollo-router-scaffold/templates/base/xtask/Cargo.template.toml @@ -13,7 +13,7 @@ apollo-router-scaffold = { path ="{{integration_test}}apollo-router-scaffold" } {{#if branch}} apollo-router-scaffold = { git="https://github.com/apollographql/router.git", branch="{{branch}}" } {{else}} -apollo-router-scaffold = { git = "https://github.com/apollographql/router.git", tag = "v1.59.0" } +apollo-router-scaffold = { git = "https://github.com/apollographql/router.git", tag = "v1.59.1" } {{/if}} {{/if}} anyhow = "1.0.58" diff --git a/apollo-router/Cargo.toml b/apollo-router/Cargo.toml index e47245d773..5563e7d699 100644 --- a/apollo-router/Cargo.toml +++ b/apollo-router/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "apollo-router" -version = "1.59.0" +version = "1.59.1" authors = ["Apollo Graph, Inc. "] repository = "https://github.com/apollographql/router/" documentation = "https://docs.rs/apollo-router" @@ -59,7 +59,7 @@ ci = [] access-json = "0.1.0" anyhow = "1.0.86" apollo-compiler.workspace = true -apollo-federation = { path = "../apollo-federation", version = "=1.59.0" } +apollo-federation = { path = "../apollo-federation", version = "=1.59.1" } arc-swap = "1.6.0" async-channel = "1.9.0" async-compression = { version = "0.4.6", features = [ diff --git a/apollo-router/src/axum_factory/axum_http_server_factory.rs b/apollo-router/src/axum_factory/axum_http_server_factory.rs index bf53143815..df6d9743d4 100644 --- a/apollo-router/src/axum_factory/axum_http_server_factory.rs +++ b/apollo-router/src/axum_factory/axum_http_server_factory.rs @@ -88,16 +88,16 @@ fn session_count_instrument() -> ObservableGauge { .init() } -struct SessionCountGuard; +struct ActiveSessionCountGuard; -impl SessionCountGuard { +impl ActiveSessionCountGuard { fn start() -> Self { ACTIVE_SESSION_COUNT.fetch_add(1, Ordering::Acquire); Self } } -impl Drop for SessionCountGuard { +impl Drop for ActiveSessionCountGuard { fn drop(&mut self) { ACTIVE_SESSION_COUNT.fetch_sub(1, Ordering::Acquire); } @@ -655,7 +655,7 @@ async fn handle_graphql( experimental_log_on_broken_pipe: bool, http_request: Request>, ) -> impl IntoResponse { - let _guard = SessionCountGuard::start(); + let _guard = ActiveSessionCountGuard::start(); let (parts, body) = http_request.into_parts(); diff --git a/apollo-router/src/axum_factory/listeners.rs b/apollo-router/src/axum_factory/listeners.rs index 52ea352979..17881d47bb 100644 --- a/apollo-router/src/axum_factory/listeners.rs +++ b/apollo-router/src/axum_factory/listeners.rs @@ -14,6 +14,8 @@ use futures::channel::oneshot; use futures::prelude::*; use hyper::server::conn::Http; use multimap::MultiMap; +use opentelemetry::metrics::MeterProvider; +use opentelemetry::KeyValue; #[cfg(unix)] use tokio::net::UnixListener; use tokio::sync::mpsc; @@ -26,13 +28,29 @@ use crate::axum_factory::ENDPOINT_CALLBACK; use crate::configuration::Configuration; use crate::http_server_factory::Listener; use crate::http_server_factory::NetworkStream; +use crate::metrics::meter_provider; use crate::router::ApolloRouterError; use crate::router_factory::Endpoint; use crate::ListenAddr; -static SESSION_COUNT: AtomicU64 = AtomicU64::new(0); +static TOTAL_SESSION_COUNT: AtomicU64 = AtomicU64::new(0); static MAX_FILE_HANDLES_WARN: AtomicBool = AtomicBool::new(false); +struct TotalSessionCountGuard; + +impl TotalSessionCountGuard { + fn start() -> Self { + TOTAL_SESSION_COUNT.fetch_add(1, Ordering::Acquire); + Self + } +} + +impl Drop for TotalSessionCountGuard { + fn drop(&mut self) { + TOTAL_SESSION_COUNT.fetch_sub(1, Ordering::Acquire); + } +} + #[derive(Clone, Debug)] pub(crate) struct ListenAddrAndRouter(pub(crate) ListenAddr, pub(crate) Router); @@ -214,9 +232,19 @@ pub(super) fn serve_router_on_listen_addr( let server = async move { tokio::pin!(shutdown_receiver); - let connection_shutdown = Arc::new(Notify::new()); + let _total_session_count_instrument = meter_provider() + .meter("apollo/router") + .u64_observable_gauge("apollo_router_session_count_total") + .with_description("Number of currently connected clients") + .with_callback(move |gauge| { + gauge.observe( + TOTAL_SESSION_COUNT.load(Ordering::Relaxed), + &[KeyValue::new("listener", address.to_string())], + ); + }) + .init(); - let address = address.to_string(); + let connection_shutdown = Arc::new(Notify::new()); loop { tokio::select! { @@ -234,16 +262,10 @@ pub(super) fn serve_router_on_listen_addr( tracing::info!("can accept connections again"); MAX_FILE_HANDLES_WARN.store(false, Ordering::SeqCst); } + // We only want to recognise sessions if we are the main graphql port. - if main_graphql_port { - let session_count = SESSION_COUNT.fetch_add(1, Ordering::Acquire)+1; - tracing::info!( - value.apollo_router_session_count_total = session_count, - listener = &address - ); - } + let _guard = main_graphql_port.then(TotalSessionCountGuard::start); - let address = address.clone(); let mut http_config = http_config.clone(); tokio::task::spawn(async move { // this sender must be moved into the session to track that it is still running @@ -352,15 +374,6 @@ pub(super) fn serve_router_on_listen_addr( } } } - - // We only want to recognise sessions if we are the main graphql port. - if main_graphql_port { - let session_count = SESSION_COUNT.fetch_sub(1, Ordering::Acquire)-1; - tracing::info!( - value.apollo_router_session_count_total = session_count, - listener = &address - ); - } }); } diff --git a/apollo-router/src/plugins/demand_control/cost_calculator/fixtures/subscription_query.graphql b/apollo-router/src/plugins/demand_control/cost_calculator/fixtures/subscription_query.graphql new file mode 100644 index 0000000000..6429125907 --- /dev/null +++ b/apollo-router/src/plugins/demand_control/cost_calculator/fixtures/subscription_query.graphql @@ -0,0 +1,6 @@ +subscription MessageSubscription { + messages { + subject + content + } +} diff --git a/apollo-router/src/plugins/demand_control/cost_calculator/fixtures/subscription_schema.graphql b/apollo-router/src/plugins/demand_control/cost_calculator/fixtures/subscription_schema.graphql new file mode 100644 index 0000000000..c04c47c742 --- /dev/null +++ b/apollo-router/src/plugins/demand_control/cost_calculator/fixtures/subscription_schema.graphql @@ -0,0 +1,92 @@ +schema + @link(url: "https://specs.apollo.dev/link/v1.0") + @link(url: "https://specs.apollo.dev/join/v0.4", for: EXECUTION) { + query: Query + mutation: Mutation + subscription: Subscription +} + +directive @join__directive( + graphs: [join__Graph!] + name: String! + args: join__DirectiveArguments +) repeatable on SCHEMA | OBJECT | INTERFACE | FIELD_DEFINITION + +directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE + +directive @join__field( + graph: join__Graph + requires: join__FieldSet + provides: join__FieldSet + type: String + external: Boolean + override: String + usedOverridden: Boolean + overrideLabel: String +) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION + +directive @join__graph(name: String!, url: String!) on ENUM_VALUE + +directive @join__implements( + graph: join__Graph! + interface: String! +) repeatable on OBJECT | INTERFACE + +directive @join__type( + graph: join__Graph! + key: join__FieldSet + extension: Boolean! = false + resolvable: Boolean! = true + isInterfaceObject: Boolean! = false +) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR + +directive @join__unionMember( + graph: join__Graph! + member: String! +) repeatable on UNION + +directive @link( + url: String + as: String + for: link__Purpose + import: [link__Import] +) repeatable on SCHEMA + +scalar join__DirectiveArguments + +scalar join__FieldSet + +enum join__Graph { + SUBGRAPH @join__graph(name: "subgraph", url: "http://localhost:4001") +} + +scalar link__Import + +enum link__Purpose { + """ + `SECURITY` features provide metadata necessary to securely resolve fields. + """ + SECURITY + + """ + `EXECUTION` features provide metadata necessary for operation execution. + """ + EXECUTION +} + +type Message @join__type(graph: SUBGRAPH) { + subject: String + content: String +} + +type Mutation @join__type(graph: SUBGRAPH) { + addMessage(subject: String, content: String): Message +} + +type Query @join__type(graph: SUBGRAPH) { + allMessages: [Message] +} + +type Subscription @join__type(graph: SUBGRAPH) { + messages: Message +} diff --git a/apollo-router/src/plugins/demand_control/cost_calculator/static_cost.rs b/apollo-router/src/plugins/demand_control/cost_calculator/static_cost.rs index b3f46386ce..aac7688856 100644 --- a/apollo-router/src/plugins/demand_control/cost_calculator/static_cost.rs +++ b/apollo-router/src/plugins/demand_control/cost_calculator/static_cost.rs @@ -1137,4 +1137,15 @@ mod tests { assert_eq!(estimated_cost(schema, query, variables), 1.0); } + + #[test(tokio::test)] + async fn subscription_request() { + let schema = include_str!("./fixtures/subscription_schema.graphql"); + let query = include_str!("./fixtures/subscription_query.graphql"); + let variables = "{}"; + + assert_eq!(estimated_cost(schema, query, variables), 1.0); + assert_eq!(planned_cost_js(schema, query, variables).await, 1.0); + assert_eq!(planned_cost_rust(schema, query, variables), 1.0); + } } diff --git a/apollo-router/src/query_planner/plan.rs b/apollo-router/src/query_planner/plan.rs index 076c47080c..472f246b5f 100644 --- a/apollo-router/src/query_planner/plan.rs +++ b/apollo-router/src/query_planner/plan.rs @@ -354,7 +354,8 @@ impl PlanNode { } } } - PlanNode::Subscription { primary: _, rest } => { + PlanNode::Subscription { primary, rest } => { + primary.init_parsed_operation(subgraph_schemas)?; if let Some(node) = rest.as_mut() { node.init_parsed_operations(subgraph_schemas)?; } diff --git a/apollo-router/src/query_planner/subscription.rs b/apollo-router/src/query_planner/subscription.rs index 9bb515b958..260f654c5d 100644 --- a/apollo-router/src/query_planner/subscription.rs +++ b/apollo-router/src/query_planner/subscription.rs @@ -12,10 +12,12 @@ use tower::ServiceExt; use tracing_futures::Instrument; use super::execution::ExecutionParameters; +use super::fetch::SubgraphSchemas; use super::fetch::Variables; use super::rewrites; use super::OperationKind; use crate::error::FetchError; +use crate::error::ValidationErrors; use crate::graphql::Error; use crate::graphql::Request; use crate::graphql::Response; @@ -272,4 +274,13 @@ impl SubscriptionNode { Ok(response.errors) } + + pub(crate) fn init_parsed_operation( + &mut self, + subgraph_schemas: &SubgraphSchemas, + ) -> Result<(), ValidationErrors> { + let schema = &subgraph_schemas[self.service_name.as_ref()]; + self.operation.init_parsed(schema)?; + Ok(()) + } } diff --git a/apollo-router/src/services/layers/content_negotiation.rs b/apollo-router/src/services/layers/content_negotiation.rs index 480cdc1dab..64f9a18367 100644 --- a/apollo-router/src/services/layers/content_negotiation.rs +++ b/apollo-router/src/services/layers/content_negotiation.rs @@ -293,5 +293,14 @@ mod tests { default_headers.append(ACCEPT, HeaderValue::from_static(MULTIPART_DEFER_ACCEPT)); let accepts = parse_accept(&default_headers); assert!(accepts.multipart_defer); + + // Multiple accepted types, including one with a parameter we are interested in + let mut default_headers = HeaderMap::new(); + default_headers.insert( + ACCEPT, + HeaderValue::from_static("multipart/mixed;subscriptionSpec=1.0, application/json"), + ); + let accepts = parse_accept(&default_headers); + assert!(accepts.multipart_subscription); } } diff --git a/apollo-router/tests/integration/query_planner/max_evaluated_plans.rs b/apollo-router/tests/integration/query_planner/max_evaluated_plans.rs index 6326d600ee..1f3136e8d2 100644 --- a/apollo-router/tests/integration/query_planner/max_evaluated_plans.rs +++ b/apollo-router/tests/integration/query_planner/max_evaluated_plans.rs @@ -54,6 +54,50 @@ async fn reports_evaluated_plans() { router.graceful_shutdown().await; } +#[tokio::test(flavor = "multi_thread")] +async fn does_not_exceed_max_evaluated_plans_legacy() { + let mut router = IntegrationTest::builder() + .config( + r#" + experimental_query_planner_mode: legacy + telemetry: + exporters: + metrics: + prometheus: + enabled: true + supergraph: + query_planning: + experimental_plans_limit: 4 + "#, + ) + .supergraph("tests/integration/fixtures/query_planner_max_evaluated_plans.graphql") + .build() + .await; + router.start().await; + router.assert_started().await; + router + .execute_query( + Query::builder() + .body(json!({ + "query": r#"{ t { v1 v2 v3 v4 } }"#, + "variables": {}, + })) + .build(), + ) + .await; + + let metrics = router + .get_metrics_response() + .await + .expect("failed to fetch metrics") + .text() + .await + .expect("metrics are not text?!"); + assert_evaluated_plans(&metrics, 4); + + router.graceful_shutdown().await; +} + #[tokio::test(flavor = "multi_thread")] async fn does_not_exceed_max_evaluated_plans() { let mut router = IntegrationTest::builder() diff --git a/dockerfiles/tracing/docker-compose.datadog.yml b/dockerfiles/tracing/docker-compose.datadog.yml index 4eec369eb4..cad8686c22 100644 --- a/dockerfiles/tracing/docker-compose.datadog.yml +++ b/dockerfiles/tracing/docker-compose.datadog.yml @@ -3,7 +3,7 @@ services: apollo-router: container_name: apollo-router - image: ghcr.io/apollographql/router:v1.59.0 + image: ghcr.io/apollographql/router:v1.59.1 volumes: - ./supergraph.graphql:/etc/config/supergraph.graphql - ./router/datadog.router.yaml:/etc/config/configuration.yaml diff --git a/dockerfiles/tracing/docker-compose.jaeger.yml b/dockerfiles/tracing/docker-compose.jaeger.yml index 72a2857397..f84e25a10d 100644 --- a/dockerfiles/tracing/docker-compose.jaeger.yml +++ b/dockerfiles/tracing/docker-compose.jaeger.yml @@ -4,7 +4,7 @@ services: apollo-router: container_name: apollo-router #build: ./router - image: ghcr.io/apollographql/router:v1.59.0 + image: ghcr.io/apollographql/router:v1.59.1 volumes: - ./supergraph.graphql:/etc/config/supergraph.graphql - ./router/jaeger.router.yaml:/etc/config/configuration.yaml diff --git a/dockerfiles/tracing/docker-compose.zipkin.yml b/dockerfiles/tracing/docker-compose.zipkin.yml index 0ebdfb9ce7..cf71996327 100644 --- a/dockerfiles/tracing/docker-compose.zipkin.yml +++ b/dockerfiles/tracing/docker-compose.zipkin.yml @@ -4,7 +4,7 @@ services: apollo-router: container_name: apollo-router build: ./router - image: ghcr.io/apollographql/router:v1.59.0 + image: ghcr.io/apollographql/router:v1.59.1 volumes: - ./supergraph.graphql:/etc/config/supergraph.graphql - ./router/zipkin.router.yaml:/etc/config/configuration.yaml diff --git a/docs/source/routing/security/jwt.mdx b/docs/source/routing/security/jwt.mdx index ece4d02c77..e9fc266660 100644 --- a/docs/source/routing/security/jwt.mdx +++ b/docs/source/routing/security/jwt.mdx @@ -745,12 +745,16 @@ If you _do_ need to pass entire JWTs to subgraphs, you can do so via the GraphOS 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](/router/configuration/telemetry/exporters/metrics/prometheus), the JWT authentication plugin provides and exports the following metrics: +If your router [exports metrics](/router/configuration/telemetry/exporters/metrics), the JWT authentication plugin exports the `apollo.router.operations.authentication.jwt` metric. You can use the metric's `authentication.jwt.failed` attribute to count failed authentications. If the `authentication.jwt.failed` attribute is absent or `false`, the authentication succeeded. + + + +Before [v1.59.0](https://github.com/apollographql/router/releases/tag/v1.59.0), the JWT authentication exported the following metrics: - `apollo_authentication_failure_count` - `apollo_authentication_success_count` -Those metrics have the following shapes: +These metrics have the following shapes: ``` # HELP apollo_authentication_failure_count apollo_authentication_failure_count @@ -762,6 +766,10 @@ apollo_authentication_failure_count{kind="JWT",service_name="apollo-router"} 1 apollo_authentication_success_count{kind="JWT",service_name="apollo-router"} 11 ``` +These metrics are [deprecated](graphos/reference/router/telemetry/instrumentation/standard-instruments#deprecated). Please update to the most recent router version to use the updated `apollo.router.operations.authentication.jwt` metric. + + + ## Additional resources You can use the Apollo Solutions [router JWKS generator](https://github.com/apollosolutions/router-jwks-generator) to create a router configuration file for use with the authentication plugin. diff --git a/helm/chart/router/Chart.yaml b/helm/chart/router/Chart.yaml index 95cf5805eb..3302fa15fb 100644 --- a/helm/chart/router/Chart.yaml +++ b/helm/chart/router/Chart.yaml @@ -20,10 +20,10 @@ type: application # so it matches the shape of our release process and release automation. # By proxy of that decision, this version uses SemVer 2.0.0, though the prefix # of "v" is not included. -version: 1.59.0 +version: 1.59.1 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "v1.59.0" +appVersion: "v1.59.1" diff --git a/helm/chart/router/README.md b/helm/chart/router/README.md index a9a5af6b71..705a48e567 100644 --- a/helm/chart/router/README.md +++ b/helm/chart/router/README.md @@ -2,7 +2,7 @@ [router](https://github.com/apollographql/router) Rust Graph Routing runtime for Apollo Federation -![Version: 1.59.0](https://img.shields.io/badge/Version-1.59.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v1.59.0](https://img.shields.io/badge/AppVersion-v1.59.0-informational?style=flat-square) +![Version: 1.59.1](https://img.shields.io/badge/Version-1.59.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v1.59.1](https://img.shields.io/badge/AppVersion-v1.59.1-informational?style=flat-square) ## Prerequisites @@ -11,7 +11,7 @@ ## Get Repo Info ```console -helm pull oci://ghcr.io/apollographql/helm-charts/router --version 1.59.0 +helm pull oci://ghcr.io/apollographql/helm-charts/router --version 1.59.1 ``` ## Install Chart @@ -19,7 +19,7 @@ helm pull oci://ghcr.io/apollographql/helm-charts/router --version 1.59.0 **Important:** only helm3 is supported ```console -helm upgrade --install [RELEASE_NAME] oci://ghcr.io/apollographql/helm-charts/router --version 1.59.0 --values my-values.yaml +helm upgrade --install [RELEASE_NAME] oci://ghcr.io/apollographql/helm-charts/router --version 1.59.1 --values my-values.yaml ``` _See [configuration](#configuration) below._ @@ -98,4 +98,4 @@ helm show values oci://ghcr.io/apollographql/helm-charts/router | virtualservice.enabled | bool | `false` | | ---------------------------------------------- -Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1) +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/licenses.html b/licenses.html index 3b497f5e45..208b06d19a 100644 --- a/licenses.html +++ b/licenses.html @@ -6122,7 +6122,6 @@

Used by:

  • erased-serde
  • ghost
  • itoa
  • -
  • libc
  • linkme
  • paste
  • prettyplease
  • @@ -12605,6 +12604,7 @@

    Used by:

  • graphql_query_derive
  • http-serde
  • ident_case
  • +
  • libc
  • libssh2-sys
  • linkme-impl
  • md5
  • diff --git a/scripts/install.sh b/scripts/install.sh index 4403b9866e..560319b7db 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -11,7 +11,7 @@ BINARY_DOWNLOAD_PREFIX="https://github.com/apollographql/router/releases/downloa # Router version defined in apollo-router's Cargo.toml # Note: Change this line manually during the release steps. -PACKAGE_VERSION="v1.59.0" +PACKAGE_VERSION="v1.59.1" download_binary() { downloader --check