From d588838d67a193efa5a02350448e05a02f2f70ff Mon Sep 17 00:00:00 2001 From: bryn Date: Wed, 12 Jun 2024 22:11:29 +0100 Subject: [PATCH 1/8] Add cost information to protobuf traces --- .../src/plugins/demand_control/mod.rs | 2 + .../strategy/static_estimated.rs | 1 + .../plugins/telemetry/config_new/cost/mod.rs | 11 +- .../src/plugins/telemetry/config_new/mod.rs | 2 +- apollo-router/src/plugins/telemetry/mod.rs | 33 +- .../telemetry/tracing/apollo_telemetry.rs | 62 +- apollo-router/tests/apollo_reports.rs | 59 +- .../tests/fixtures/apollo_reports.router.yaml | 7 + .../apollo_reports__demand_control_trace.snap | 568 ++++++++++++++++++ 9 files changed, 726 insertions(+), 19 deletions(-) create mode 100644 apollo-router/tests/snapshots/apollo_reports__demand_control_trace.snap diff --git a/apollo-router/src/plugins/demand_control/mod.rs b/apollo-router/src/plugins/demand_control/mod.rs index fc36115b2e..57400ca40c 100644 --- a/apollo-router/src/plugins/demand_control/mod.rs +++ b/apollo-router/src/plugins/demand_control/mod.rs @@ -43,6 +43,7 @@ pub(crate) struct CostContext { pub(crate) estimated: f64, pub(crate) actual: f64, pub(crate) result: &'static str, + pub(crate) strategy: &'static str, } impl Default for CostContext { @@ -51,6 +52,7 @@ impl Default for CostContext { estimated: 0.0, actual: 0.0, result: "COST_OK", + strategy: "COST_STRATEGY_UNKNOWN", } } } diff --git a/apollo-router/src/plugins/demand_control/strategy/static_estimated.rs b/apollo-router/src/plugins/demand_control/strategy/static_estimated.rs index 6e7447d6b4..41de6926b4 100644 --- a/apollo-router/src/plugins/demand_control/strategy/static_estimated.rs +++ b/apollo-router/src/plugins/demand_control/strategy/static_estimated.rs @@ -22,6 +22,7 @@ impl StrategyImpl for StaticEstimated { .and_then(|cost| { request.context.extensions().with_lock(|mut lock| { let cost_result = lock.get_or_default_mut::(); + cost_result.strategy = "static_estimated"; cost_result.estimated = cost; if cost > self.max { Err( diff --git a/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs b/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs index 02e20da6a8..b234d476f9 100644 --- a/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs +++ b/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use opentelemetry::metrics::MeterProvider; -use opentelemetry_api::KeyValue; +use opentelemetry_api::{Key, KeyValue}; use parking_lot::Mutex; use schemars::JsonSchema; use serde::Deserialize; @@ -24,6 +24,15 @@ use crate::services::supergraph::Request; use crate::services::supergraph::Response; use crate::Context; +pub(crate) const APOLLO_PRIVATE_COST_ESTIMATED: Key = + Key::from_static_str("apollo_private.cost.estimated"); +pub(crate) const APOLLO_PRIVATE_COST_ACTUAL: Key = + Key::from_static_str("apollo_private.cost.actual"); +pub(crate) const APOLLO_PRIVATE_COST_STRATEGY: Key = + Key::from_static_str("apollo_private.cost.strategy"); +pub(crate) const APOLLO_PRIVATE_COST_RESULT: Key = + Key::from_static_str("apollo_private.cost.result"); + static COST_ESTIMATED: &str = "cost.estimated"; static COST_ACTUAL: &str = "cost.actual"; static COST_DELTA: &str = "cost.delta"; diff --git a/apollo-router/src/plugins/telemetry/config_new/mod.rs b/apollo-router/src/plugins/telemetry/config_new/mod.rs index b66958db4f..dd719e9300 100644 --- a/apollo-router/src/plugins/telemetry/config_new/mod.rs +++ b/apollo-router/src/plugins/telemetry/config_new/mod.rs @@ -18,7 +18,7 @@ pub(crate) mod attributes; pub(crate) mod conditions; mod conditional; -mod cost; +pub(crate) mod cost; pub(crate) mod events; mod experimental_when_header; pub(crate) mod extendable; diff --git a/apollo-router/src/plugins/telemetry/mod.rs b/apollo-router/src/plugins/telemetry/mod.rs index c980c333f8..f3c355992a 100644 --- a/apollo-router/src/plugins/telemetry/mod.rs +++ b/apollo-router/src/plugins/telemetry/mod.rs @@ -86,12 +86,17 @@ use crate::metrics::filter::FilterMeterProvider; use crate::metrics::meter_provider; use crate::plugin::Plugin; use crate::plugin::PluginInit; +use crate::plugins::demand_control::CostContext; use crate::plugins::telemetry::apollo::ForwardHeaders; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::node::Id::ResponseName; use crate::plugins::telemetry::apollo_exporter::proto::reports::StatsContext; use crate::plugins::telemetry::config::AttributeValue; use crate::plugins::telemetry::config::MetricsCommon; use crate::plugins::telemetry::config::TracingCommon; +use crate::plugins::telemetry::config_new::cost::{ + APOLLO_PRIVATE_COST_ACTUAL, APOLLO_PRIVATE_COST_ESTIMATED, APOLLO_PRIVATE_COST_RESULT, + APOLLO_PRIVATE_COST_STRATEGY, +}; use crate::plugins::telemetry::config_new::graphql::GraphQLInstruments; use crate::plugins::telemetry::config_new::instruments::SupergraphInstruments; use crate::plugins::telemetry::dynamic_attribute::SpanDynAttribute; @@ -588,15 +593,16 @@ impl Plugin for Telemetry { (req.context.clone(), custom_instruments, custom_attributes, supergraph_events, custom_graphql_instruments) }, - move |(ctx, custom_instruments, custom_attributes, supergraph_events, custom_graphql_instruments): (Context, SupergraphInstruments, Vec, SupergraphEvents, GraphQLInstruments), fut| { + move |(ctx, custom_instruments, mut custom_attributes, supergraph_events, custom_graphql_instruments): (Context, SupergraphInstruments, Vec, SupergraphEvents, GraphQLInstruments), fut| { let config = config_map_res.clone(); let sender = metrics_sender.clone(); let start = Instant::now(); async move { let span = Span::current(); - span.set_span_dyn_attributes(custom_attributes); let mut result: Result = fut.await; + add_cost_attributes(&ctx, &mut custom_attributes); + span.set_span_dyn_attributes(custom_attributes); match &result { Ok(resp) => { span.set_span_dyn_attributes(config.instrumentation.spans.supergraph.attributes.on_response(resp)); @@ -774,6 +780,29 @@ impl Plugin for Telemetry { } } +fn add_cost_attributes(context: &Context, custom_attributes: &mut Vec) { + context.extensions().with_lock(|c| { + if let Some(cost) = c.get::().cloned() { + custom_attributes.push(KeyValue::new( + APOLLO_PRIVATE_COST_ESTIMATED.clone(), + AttributeValue::I64(cost.estimated as i64), + )); + custom_attributes.push(KeyValue::new( + APOLLO_PRIVATE_COST_ACTUAL.clone(), + AttributeValue::I64(cost.actual as i64), + )); + custom_attributes.push(KeyValue::new( + APOLLO_PRIVATE_COST_RESULT.clone(), + AttributeValue::String(cost.result.into()), + )); + custom_attributes.push(KeyValue::new( + APOLLO_PRIVATE_COST_STRATEGY.clone(), + AttributeValue::String(cost.strategy.into()), + )); + } + }); +} + impl Telemetry { pub(crate) fn activate(&self) { let mut activation = self.activation.lock(); diff --git a/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs b/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs index a916e35986..4f210eebbc 100644 --- a/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs +++ b/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs @@ -53,9 +53,9 @@ use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::query_pla use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::query_plan_node::ParallelNode; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::query_plan_node::ResponsePathElement; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::query_plan_node::SequenceNode; -use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::Details; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::Http; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::QueryPlanNode; +use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::{Details, Limits}; use crate::plugins::telemetry::apollo_exporter::ApolloExporter; use crate::plugins::telemetry::apollo_otlp_exporter::ApolloOtlpExporter; use crate::plugins::telemetry::config::Sampler; @@ -96,6 +96,14 @@ const APOLLO_PRIVATE_HTTP_RESPONSE_HEADERS: Key = Key::from_static_str("apollo_private.http.response_headers"); pub(crate) const APOLLO_PRIVATE_OPERATION_SIGNATURE: Key = Key::from_static_str("apollo_private.operation_signature"); +pub(crate) const APOLLO_PRIVATE_COST_ESTIMATED: Key = + Key::from_static_str("apollo_private.cost.estimated"); +pub(crate) const APOLLO_PRIVATE_COST_ACTUAL: Key = + Key::from_static_str("apollo_private.cost.actual"); +pub(crate) const APOLLO_PRIVATE_COST_STRATEGY: Key = + Key::from_static_str("apollo_private.cost.strategy"); +pub(crate) const APOLLO_PRIVATE_COST_RESULT: Key = + Key::from_static_str("apollo_private.cost.result"); pub(crate) const APOLLO_PRIVATE_FTV1: Key = Key::from_static_str("apollo_private.ftv1"); const PATH: Key = Key::from_static_str("graphql.path"); const SUBGRAPH_NAME: Key = Key::from_static_str("apollo.subgraph.name"); @@ -110,7 +118,7 @@ pub(crate) const OPERATION_SUBTYPE: Key = Key::from_static_str("apollo_private.o const EXT_TRACE_ID: Key = Key::from_static_str("trace_id"); /// The set of attributes to include when sending to the Apollo Reports protocol. -const REPORTS_INCLUDE_ATTRS: [Key; 18] = [ +const REPORTS_INCLUDE_ATTRS: [Key; 22] = [ APOLLO_PRIVATE_REQUEST, APOLLO_PRIVATE_DURATION_NS_KEY, APOLLO_PRIVATE_SENT_TIME_OFFSET, @@ -119,6 +127,10 @@ const REPORTS_INCLUDE_ATTRS: [Key; 18] = [ APOLLO_PRIVATE_HTTP_RESPONSE_HEADERS, APOLLO_PRIVATE_OPERATION_SIGNATURE, APOLLO_PRIVATE_FTV1, + APOLLO_PRIVATE_COST_STRATEGY, + APOLLO_PRIVATE_COST_RESULT, + APOLLO_PRIVATE_COST_ESTIMATED, + APOLLO_PRIVATE_COST_ACTUAL, PATH, SUBGRAPH_NAME, CLIENT_NAME_KEY, @@ -261,6 +273,7 @@ enum TreeData { operation_signature: String, operation_name: String, variables_json: HashMap, + limits: Option, }, QueryPlanNode(QueryPlanNode), DeferPrimary(DeferNodePrimary), @@ -395,6 +408,7 @@ impl Exporter { operation_signature, operation_name, variables_json, + limits, } => { root_trace.field_execution_weight = self.field_execution_weight; root_trace.signature = operation_signature; @@ -402,6 +416,7 @@ impl Exporter { variables_json, operation_name, }); + root_trace.limits = limits; results.push(root_trace.clone()); } TreeData::Execution(operation_type) => { @@ -572,6 +587,35 @@ impl Exporter { )] } SUPERGRAPH_SPAN_NAME => { + let limits = span + .attributes + .get(&APOLLO_PRIVATE_COST_RESULT) + .and_then(extract_string) + .map(|result| { + Limits { + result, + strategy: span + .attributes + .get(&APOLLO_PRIVATE_COST_STRATEGY) + .and_then(extract_string) + .unwrap_or_default(), + cost_estimated: span + .attributes + .get(&APOLLO_PRIVATE_COST_ESTIMATED) + .and_then(extract_u64) + .unwrap_or_default(), + cost_actual: span + .attributes + .get(&APOLLO_PRIVATE_COST_ACTUAL) + .and_then(extract_u64) + .unwrap_or_default(), + // Not extracted yet + depth: 0, + height: 0, + alias_count: 0, + root_field_count: 0, + } + }); //Currently some data is in the supergraph span as we don't have the a request hook in plugin. child_nodes.push(TreeData::Supergraph { operation_signature: span @@ -589,6 +633,7 @@ impl Exporter { .get(&APOLLO_PRIVATE_GRAPHQL_VARIABLES) .and_then(extract_json) .unwrap_or_default(), + limits, }); child_nodes } @@ -751,6 +796,7 @@ impl Exporter { .and_then(extract_string) .unwrap_or_default(), variables_json: HashMap::new(), + limits: None, }); child_nodes.push(TreeData::Execution( @@ -821,6 +867,18 @@ pub(crate) fn extract_i64(v: &Value) -> Option { } } +pub(crate) fn extract_u64(v: &Value) -> Option { + if let Value::I64(v) = v { + if *v > 0 { + Some(*v as u64) + } else { + None + } + } else { + None + } +} + pub(crate) fn extract_ftv1_trace_with_error_count( v: &Value, error_config: &ErrorConfiguration, diff --git a/apollo-router/tests/apollo_reports.rs b/apollo-router/tests/apollo_reports.rs index ba847ae4e1..feb8fd6135 100644 --- a/apollo-router/tests/apollo_reports.rs +++ b/apollo-router/tests/apollo_reports.rs @@ -54,6 +54,7 @@ async fn config( use_legacy_request_span: bool, batch: bool, reports: Arc>>, + demand_control: bool, ) -> (JoinHandle<()>, serde_json::Value) { std::env::set_var("APOLLO_KEY", "test"); std::env::set_var("APOLLO_GRAPH_REF", "test"); @@ -89,6 +90,10 @@ async fn config( Some(serde_json::Value::Bool(use_legacy_request_span)) }) .expect("Could not sub in endpoint"); + config = jsonpath_lib::replace_with(config, "$.preview_demand_control.enabled", &mut |_| { + Some(serde_json::Value::Bool(demand_control)) + }) + .expect("Could not sub in endpoint"); (task, config) } @@ -96,8 +101,9 @@ async fn get_router_service( reports: Arc>>, use_legacy_request_span: bool, mocked: bool, + demand_control: bool, ) -> (JoinHandle<()>, BoxCloneService) { - let (task, config) = config(use_legacy_request_span, false, reports).await; + let (task, config) = config(use_legacy_request_span, false, reports, demand_control).await; let builder = TestHarness::builder() .try_log_level("INFO") .configuration_json(config) @@ -121,8 +127,9 @@ async fn get_batch_router_service( reports: Arc>>, use_legacy_request_span: bool, mocked: bool, + demand_control: bool, ) -> (JoinHandle<()>, BoxCloneService) { - let (task, config) = config(use_legacy_request_span, true, reports).await; + let (task, config) = config(use_legacy_request_span, true, reports, demand_control).await; let builder = TestHarness::builder() .try_log_level("INFO") .configuration_json(config) @@ -211,6 +218,7 @@ async fn get_trace_report( reports: Arc>>, request: router::Request, use_legacy_request_span: bool, + demand_control: bool, ) -> Report { get_report( get_router_service, @@ -218,6 +226,7 @@ async fn get_trace_report( use_legacy_request_span, false, request, + demand_control, |r| { !r.traces_per_query .values() @@ -241,6 +250,7 @@ async fn get_batch_trace_report( use_legacy_request_span, false, request, + false, |r| { !r.traces_per_query .values() @@ -269,6 +279,7 @@ async fn get_metrics_report(reports: Arc>>, request: router::R false, false, request, + false, has_metrics, ) .await @@ -291,17 +302,19 @@ async fn get_metrics_report_mocked( false, true, request, + false, has_metrics, ) .await } async fn get_report bool + Send + Sync + Copy + 'static>( - service_fn: impl FnOnce(Arc>>, bool, bool) -> Fut, + service_fn: impl FnOnce(Arc>>, bool, bool, bool) -> Fut, reports: Arc>>, use_legacy_request_span: bool, mocked: bool, request: router::Request, + demand_control: bool, filter: T, ) -> Report where @@ -309,7 +322,13 @@ where { let _guard = TEST.lock().await; reports.lock().await.clear(); - let (task, mut service) = service_fn(reports.clone(), use_legacy_request_span, mocked).await; + let (task, mut service) = service_fn( + reports.clone(), + use_legacy_request_span, + mocked, + demand_control, + ) + .await; let response = service .ready() .await @@ -358,7 +377,7 @@ async fn get_batch_stats_report bool + Send + Sync + Copy + ' ) -> u64 { let _guard = TEST.lock().await; reports.lock().await.clear(); - let (task, mut service) = get_batch_router_service(reports.clone(), mocked, false).await; + let (task, mut service) = get_batch_router_service(reports.clone(), mocked, false, false).await; let response = service .ready() .await @@ -402,7 +421,7 @@ async fn non_defer() { .unwrap(); let req: router::Request = request.try_into().expect("could not convert request"); let reports = Arc::new(Mutex::new(vec![])); - let report = get_trace_report(reports, req, use_legacy_request_span).await; + let report = get_trace_report(reports, req, use_legacy_request_span, false).await; assert_report!(report); } } @@ -418,7 +437,7 @@ async fn test_condition_if() { .unwrap(); let req: router::Request = request.try_into().expect("could not convert request"); let reports = Arc::new(Mutex::new(vec![])); - let report = get_trace_report(reports, req, use_legacy_request_span).await; + let report = get_trace_report(reports, req, use_legacy_request_span, false).await; assert_report!(report); } } @@ -434,7 +453,7 @@ async fn test_condition_else() { .unwrap(); let req: router::Request = request.try_into().expect("could not convert request"); let reports = Arc::new(Mutex::new(vec![])); - let report = get_trace_report(reports, req, use_legacy_request_span).await; + let report = get_trace_report(reports, req, use_legacy_request_span, false).await; assert_report!(report); } } @@ -448,7 +467,7 @@ async fn test_trace_id() { .unwrap(); let req: router::Request = request.try_into().expect("could not convert request"); let reports = Arc::new(Mutex::new(vec![])); - let report = get_trace_report(reports, req, use_legacy_request_span).await; + let report = get_trace_report(reports, req, use_legacy_request_span, false).await; assert_report!(report); } } @@ -487,7 +506,7 @@ async fn test_client_name() { .unwrap(); let req: router::Request = request.try_into().expect("could not convert request"); let reports = Arc::new(Mutex::new(vec![])); - let report = get_trace_report(reports, req, use_legacy_request_span).await; + let report = get_trace_report(reports, req, use_legacy_request_span, false).await; assert_report!(report); } } @@ -502,7 +521,7 @@ async fn test_client_version() { .unwrap(); let req: router::Request = request.try_into().expect("could not convert request"); let reports = Arc::new(Mutex::new(vec![])); - let report = get_trace_report(reports, req, use_legacy_request_span).await; + let report = get_trace_report(reports, req, use_legacy_request_span, false).await; assert_report!(report); } } @@ -518,7 +537,7 @@ async fn test_send_header() { .unwrap(); let req: router::Request = request.try_into().expect("could not convert request"); let reports = Arc::new(Mutex::new(vec![])); - let report = get_trace_report(reports, req, use_legacy_request_span).await; + let report = get_trace_report(reports, req, use_legacy_request_span, false).await; assert_report!(report); } } @@ -560,7 +579,7 @@ async fn test_send_variable_value() { .unwrap(); let req: router::Request = request.try_into().expect("could not convert request"); let reports = Arc::new(Mutex::new(vec![])); - let report = get_trace_report(reports, req, use_legacy_request_span).await; + let report = get_trace_report(reports, req, use_legacy_request_span, false).await; assert_report!(report); } } @@ -620,3 +639,17 @@ async fn test_stats_mocked() { }); }); } + +#[tokio::test(flavor = "multi_thread")] +async fn test_demand_control_trace() { + for use_legacy_request_span in [true, false] { + let request = supergraph::Request::fake_builder() + .query("query{topProducts{name reviews {author{name}} reviews{author{name}}}}") + .build() + .unwrap(); + let req: router::Request = request.try_into().expect("could not convert request"); + let reports = Arc::new(Mutex::new(vec![])); + let report = get_trace_report(reports, req, use_legacy_request_span, true).await; + assert_report!(report); + } +} diff --git a/apollo-router/tests/fixtures/apollo_reports.router.yaml b/apollo-router/tests/fixtures/apollo_reports.router.yaml index 846c40410d..a3cd9c571a 100644 --- a/apollo-router/tests/fixtures/apollo_reports.router.yaml +++ b/apollo-router/tests/fixtures/apollo_reports.router.yaml @@ -3,6 +3,13 @@ include_subgraph_errors: rhai: scripts: tests/fixtures main: test_callbacks.rhai +preview_demand_control: + mode: measure + enabled: false + strategy: + static_estimated: + max: 1500 + list_size: 10 telemetry: instrumentation: spans: diff --git a/apollo-router/tests/snapshots/apollo_reports__demand_control_trace.snap b/apollo-router/tests/snapshots/apollo_reports__demand_control_trace.snap new file mode 100644 index 0000000000..3ab1b3fbfd --- /dev/null +++ b/apollo-router/tests/snapshots/apollo_reports__demand_control_trace.snap @@ -0,0 +1,568 @@ +--- +source: apollo-router/tests/apollo_reports.rs +expression: report +--- +header: + graph_ref: test + hostname: "[hostname]" + agent_version: "[agent_version]" + service_version: "" + runtime_version: rust + uname: "[uname]" + executable_schema_id: "[executable_schema_id]" +traces_per_query: + "# -\n{topProducts{name reviews{author{name}}reviews{author{name}}}}": + trace: + - start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: + variables_json: {} + operation_name: "" + client_name: "" + client_version: "" + operation_type: query + operation_subtype: "" + http: + method: 4 + request_headers: {} + response_headers: + my_trace_id: "[my_trace_id]" + status_code: 0 + cache_policy: ~ + query_plan: + node: + Sequence: + nodes: + - node: + Fetch: + service_name: products + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[Product]" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 2 + id: + ResponseName: topProducts + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + node: + node: + Fetch: + service_name: reviews + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 1 + id: + ResponseName: reviews + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 2 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + - id: + FieldName: reviews + - id: + FieldName: author + node: + node: + Fetch: + service_name: accounts + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: + result: COST_OK + strategy: static_estimated + cost_estimated: 230 + cost_actual: 19 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 + stats_with_context: [] + referenced_fields_by_type: {} + query_metadata: ~ +end_time: "[end_time]" +operation_count: 0 +operation_count_by_type: [] +traces_pre_aggregated: true +extended_references_enabled: false From 04afe06cdbfbaa256f4a3de13d2860172fb6c3a8 Mon Sep 17 00:00:00 2001 From: bryn Date: Thu, 13 Jun 2024 11:32:45 +0100 Subject: [PATCH 2/8] Add batching tests --- apollo-router/tests/apollo_reports.rs | 34 +- .../fixtures/apollo_reports_batch.router.yaml | 7 + ...pollo_reports__demand_control_trace-2.snap | 568 +++++++++ ...ports__demand_control_trace_batched-2.snap | 1113 +++++++++++++++++ ...reports__demand_control_trace_batched.snap | 1113 +++++++++++++++++ 5 files changed, 2832 insertions(+), 3 deletions(-) create mode 100644 apollo-router/tests/snapshots/apollo_reports__demand_control_trace-2.snap create mode 100644 apollo-router/tests/snapshots/apollo_reports__demand_control_trace_batched-2.snap create mode 100644 apollo-router/tests/snapshots/apollo_reports__demand_control_trace_batched.snap diff --git a/apollo-router/tests/apollo_reports.rs b/apollo-router/tests/apollo_reports.rs index feb8fd6135..11a1288273 100644 --- a/apollo-router/tests/apollo_reports.rs +++ b/apollo-router/tests/apollo_reports.rs @@ -243,6 +243,7 @@ async fn get_batch_trace_report( reports: Arc>>, request: router::Request, use_legacy_request_span: bool, + demand_control: bool, ) -> Report { get_report( get_batch_router_service, @@ -250,7 +251,7 @@ async fn get_batch_trace_report( use_legacy_request_span, false, request, - false, + demand_control, |r| { !r.traces_per_query .values() @@ -491,7 +492,8 @@ async fn test_batch_trace_id() { hyper::Body::from(result) }); let reports = Arc::new(Mutex::new(vec![])); - let report = get_batch_trace_report(reports, request.into(), use_legacy_request_span).await; + let report = + get_batch_trace_report(reports, request.into(), use_legacy_request_span, false).await; assert_report!(report); } } @@ -563,7 +565,8 @@ async fn test_batch_send_header() { hyper::Body::from(result) }); let reports = Arc::new(Mutex::new(vec![])); - let report = get_batch_trace_report(reports, request.into(), use_legacy_request_span).await; + let report = + get_batch_trace_report(reports, request.into(), use_legacy_request_span, false).await; assert_report!(report); } } @@ -653,3 +656,28 @@ async fn test_demand_control_trace() { assert_report!(report); } } + +#[tokio::test(flavor = "multi_thread")] +async fn test_demand_control_trace_batched() { + for use_legacy_request_span in [true, false] { + let request = supergraph::Request::fake_builder() + .query("query{topProducts{name reviews {author{name}} reviews{author{name}}}}") + .build() + .unwrap() + .supergraph_request + .map(|req| { + // Modify the request so that it is a valid array of requests. + let mut json_bytes = serde_json::to_vec(&req).unwrap(); + let mut result = vec![b'[']; + result.append(&mut json_bytes.clone()); + result.push(b','); + result.append(&mut json_bytes); + result.push(b']'); + hyper::Body::from(result) + }); + let req: router::Request = request.try_into().expect("could not convert request"); + let reports = Arc::new(Mutex::new(vec![])); + let report = get_batch_trace_report(reports, req, use_legacy_request_span, true).await; + assert_report!(report); + } +} diff --git a/apollo-router/tests/fixtures/apollo_reports_batch.router.yaml b/apollo-router/tests/fixtures/apollo_reports_batch.router.yaml index 29ad9c9630..5790a7aa65 100644 --- a/apollo-router/tests/fixtures/apollo_reports_batch.router.yaml +++ b/apollo-router/tests/fixtures/apollo_reports_batch.router.yaml @@ -6,6 +6,13 @@ rhai: main: test_callbacks.rhai include_subgraph_errors: all: true +preview_demand_control: + mode: measure + enabled: false + strategy: + static_estimated: + max: 1500 + list_size: 10 telemetry: exporters: tracing: diff --git a/apollo-router/tests/snapshots/apollo_reports__demand_control_trace-2.snap b/apollo-router/tests/snapshots/apollo_reports__demand_control_trace-2.snap new file mode 100644 index 0000000000..3ab1b3fbfd --- /dev/null +++ b/apollo-router/tests/snapshots/apollo_reports__demand_control_trace-2.snap @@ -0,0 +1,568 @@ +--- +source: apollo-router/tests/apollo_reports.rs +expression: report +--- +header: + graph_ref: test + hostname: "[hostname]" + agent_version: "[agent_version]" + service_version: "" + runtime_version: rust + uname: "[uname]" + executable_schema_id: "[executable_schema_id]" +traces_per_query: + "# -\n{topProducts{name reviews{author{name}}reviews{author{name}}}}": + trace: + - start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: + variables_json: {} + operation_name: "" + client_name: "" + client_version: "" + operation_type: query + operation_subtype: "" + http: + method: 4 + request_headers: {} + response_headers: + my_trace_id: "[my_trace_id]" + status_code: 0 + cache_policy: ~ + query_plan: + node: + Sequence: + nodes: + - node: + Fetch: + service_name: products + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[Product]" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 2 + id: + ResponseName: topProducts + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + node: + node: + Fetch: + service_name: reviews + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 1 + id: + ResponseName: reviews + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 2 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + - id: + FieldName: reviews + - id: + FieldName: author + node: + node: + Fetch: + service_name: accounts + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: + result: COST_OK + strategy: static_estimated + cost_estimated: 230 + cost_actual: 19 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 + stats_with_context: [] + referenced_fields_by_type: {} + query_metadata: ~ +end_time: "[end_time]" +operation_count: 0 +operation_count_by_type: [] +traces_pre_aggregated: true +extended_references_enabled: false diff --git a/apollo-router/tests/snapshots/apollo_reports__demand_control_trace_batched-2.snap b/apollo-router/tests/snapshots/apollo_reports__demand_control_trace_batched-2.snap new file mode 100644 index 0000000000..f3b05b402a --- /dev/null +++ b/apollo-router/tests/snapshots/apollo_reports__demand_control_trace_batched-2.snap @@ -0,0 +1,1113 @@ +--- +source: apollo-router/tests/apollo_reports.rs +expression: report +--- +header: + graph_ref: test + hostname: "[hostname]" + agent_version: "[agent_version]" + service_version: "" + runtime_version: rust + uname: "[uname]" + executable_schema_id: "[executable_schema_id]" +traces_per_query: + "# -\n{topProducts{name reviews{author{name}}reviews{author{name}}}}": + trace: + - start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: + variables_json: {} + operation_name: "" + client_name: "" + client_version: "" + operation_type: query + operation_subtype: "" + http: + method: 4 + request_headers: {} + response_headers: + my_trace_id: "[my_trace_id]" + status_code: 0 + cache_policy: ~ + query_plan: + node: + Sequence: + nodes: + - node: + Fetch: + service_name: products + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[Product]" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 2 + id: + ResponseName: topProducts + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + node: + node: + Fetch: + service_name: reviews + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 1 + id: + ResponseName: reviews + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 2 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + - id: + FieldName: reviews + - id: + FieldName: author + node: + node: + Fetch: + service_name: accounts + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: + result: COST_OK + strategy: static_estimated + cost_estimated: 230 + cost_actual: 19 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 + - start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: + variables_json: {} + operation_name: "" + client_name: "" + client_version: "" + operation_type: query + operation_subtype: "" + http: + method: 4 + request_headers: {} + response_headers: + my_trace_id: "[my_trace_id]" + status_code: 0 + cache_policy: ~ + query_plan: + node: + Sequence: + nodes: + - node: + Fetch: + service_name: products + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[Product]" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 2 + id: + ResponseName: topProducts + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + node: + node: + Fetch: + service_name: reviews + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 1 + id: + ResponseName: reviews + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 2 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + - id: + FieldName: reviews + - id: + FieldName: author + node: + node: + Fetch: + service_name: accounts + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: + result: COST_OK + strategy: static_estimated + cost_estimated: 230 + cost_actual: 19 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 + stats_with_context: [] + referenced_fields_by_type: {} + query_metadata: ~ +end_time: "[end_time]" +operation_count: 0 +operation_count_by_type: [] +traces_pre_aggregated: true +extended_references_enabled: false diff --git a/apollo-router/tests/snapshots/apollo_reports__demand_control_trace_batched.snap b/apollo-router/tests/snapshots/apollo_reports__demand_control_trace_batched.snap new file mode 100644 index 0000000000..f3b05b402a --- /dev/null +++ b/apollo-router/tests/snapshots/apollo_reports__demand_control_trace_batched.snap @@ -0,0 +1,1113 @@ +--- +source: apollo-router/tests/apollo_reports.rs +expression: report +--- +header: + graph_ref: test + hostname: "[hostname]" + agent_version: "[agent_version]" + service_version: "" + runtime_version: rust + uname: "[uname]" + executable_schema_id: "[executable_schema_id]" +traces_per_query: + "# -\n{topProducts{name reviews{author{name}}reviews{author{name}}}}": + trace: + - start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: + variables_json: {} + operation_name: "" + client_name: "" + client_version: "" + operation_type: query + operation_subtype: "" + http: + method: 4 + request_headers: {} + response_headers: + my_trace_id: "[my_trace_id]" + status_code: 0 + cache_policy: ~ + query_plan: + node: + Sequence: + nodes: + - node: + Fetch: + service_name: products + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[Product]" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 2 + id: + ResponseName: topProducts + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + node: + node: + Fetch: + service_name: reviews + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 1 + id: + ResponseName: reviews + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 2 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + - id: + FieldName: reviews + - id: + FieldName: author + node: + node: + Fetch: + service_name: accounts + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: + result: COST_OK + strategy: static_estimated + cost_estimated: 230 + cost_actual: 19 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 + - start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: + variables_json: {} + operation_name: "" + client_name: "" + client_version: "" + operation_type: query + operation_subtype: "" + http: + method: 4 + request_headers: {} + response_headers: + my_trace_id: "[my_trace_id]" + status_code: 0 + cache_policy: ~ + query_plan: + node: + Sequence: + nodes: + - node: + Fetch: + service_name: products + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[Product]" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + - original_field_name: "" + type: String + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 2 + id: + ResponseName: topProducts + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + node: + node: + Fetch: + service_name: reviews + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 1 + id: + ResponseName: reviews + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 1 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "[Review]" + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: User + parent_type: Review + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: ID! + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: id + id: + ResponseName: author + id: + Index: 0 + id: + ResponseName: reviews + id: + Index: 2 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + - node: + Flatten: + response_path: + - id: + FieldName: topProducts + - id: + FieldName: reviews + - id: + FieldName: author + node: + node: + Fetch: + service_name: accounts + trace_parsing_failed: false + trace: + start_time: + seconds: "[seconds]" + nanos: "[nanos]" + end_time: + seconds: "[seconds]" + nanos: "[nanos]" + duration_ns: "[duration_ns]" + root: + original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: 0 + end_time: 0 + error: [] + child: + - original_field_name: "" + type: "[_Entity]!" + parent_type: Query + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 0 + - original_field_name: "" + type: "" + parent_type: "" + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: + - original_field_name: "" + type: String + parent_type: User + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: name + id: + Index: 1 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + operation_type: "" + operation_subtype: "" + http: ~ + cache_policy: ~ + query_plan: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: ~ + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + limits: + result: COST_OK + strategy: static_estimated + cost_estimated: 230 + cost_actual: 19 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 + stats_with_context: [] + referenced_fields_by_type: {} + query_metadata: ~ +end_time: "[end_time]" +operation_count: 0 +operation_count_by_type: [] +traces_pre_aggregated: true +extended_references_enabled: false From 3e1efcc7621345d155bce584fb0ba9b9eee69c2a Mon Sep 17 00:00:00 2001 From: bryn Date: Thu, 13 Jun 2024 11:40:53 +0100 Subject: [PATCH 3/8] Move `add_cost_attributes` to cost package --- .../plugins/telemetry/config_new/cost/mod.rs | 24 +++++++++++++++ apollo-router/src/plugins/telemetry/mod.rs | 29 +------------------ 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs b/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs index b234d476f9..6402f86787 100644 --- a/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs +++ b/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs @@ -10,6 +10,7 @@ use tower::BoxError; use super::instruments::Increment; use crate::metrics; use crate::plugins::demand_control::CostContext; +use crate::plugins::telemetry::config::AttributeValue; use crate::plugins::telemetry::config_new::attributes::SupergraphAttributes; use crate::plugins::telemetry::config_new::conditions::Condition; use crate::plugins::telemetry::config_new::extendable::Extendable; @@ -280,6 +281,29 @@ pub(crate) enum CostValue { Result, } +pub(crate) fn add_cost_attributes(context: &Context, custom_attributes: &mut Vec) { + context.extensions().with_lock(|c| { + if let Some(cost) = c.get::().cloned() { + custom_attributes.push(KeyValue::new( + APOLLO_PRIVATE_COST_ESTIMATED.clone(), + AttributeValue::I64(cost.estimated as i64), + )); + custom_attributes.push(KeyValue::new( + APOLLO_PRIVATE_COST_ACTUAL.clone(), + AttributeValue::I64(cost.actual as i64), + )); + custom_attributes.push(KeyValue::new( + APOLLO_PRIVATE_COST_RESULT.clone(), + AttributeValue::String(cost.result.into()), + )); + custom_attributes.push(KeyValue::new( + APOLLO_PRIVATE_COST_STRATEGY.clone(), + AttributeValue::String(cost.strategy.into()), + )); + } + }); +} + #[cfg(test)] mod test { use crate::context::OPERATION_NAME; diff --git a/apollo-router/src/plugins/telemetry/mod.rs b/apollo-router/src/plugins/telemetry/mod.rs index f3c355992a..d07c052a27 100644 --- a/apollo-router/src/plugins/telemetry/mod.rs +++ b/apollo-router/src/plugins/telemetry/mod.rs @@ -86,17 +86,13 @@ use crate::metrics::filter::FilterMeterProvider; use crate::metrics::meter_provider; use crate::plugin::Plugin; use crate::plugin::PluginInit; -use crate::plugins::demand_control::CostContext; use crate::plugins::telemetry::apollo::ForwardHeaders; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::node::Id::ResponseName; use crate::plugins::telemetry::apollo_exporter::proto::reports::StatsContext; use crate::plugins::telemetry::config::AttributeValue; use crate::plugins::telemetry::config::MetricsCommon; use crate::plugins::telemetry::config::TracingCommon; -use crate::plugins::telemetry::config_new::cost::{ - APOLLO_PRIVATE_COST_ACTUAL, APOLLO_PRIVATE_COST_ESTIMATED, APOLLO_PRIVATE_COST_RESULT, - APOLLO_PRIVATE_COST_STRATEGY, -}; +use crate::plugins::telemetry::config_new::cost::add_cost_attributes; use crate::plugins::telemetry::config_new::graphql::GraphQLInstruments; use crate::plugins::telemetry::config_new::instruments::SupergraphInstruments; use crate::plugins::telemetry::dynamic_attribute::SpanDynAttribute; @@ -780,29 +776,6 @@ impl Plugin for Telemetry { } } -fn add_cost_attributes(context: &Context, custom_attributes: &mut Vec) { - context.extensions().with_lock(|c| { - if let Some(cost) = c.get::().cloned() { - custom_attributes.push(KeyValue::new( - APOLLO_PRIVATE_COST_ESTIMATED.clone(), - AttributeValue::I64(cost.estimated as i64), - )); - custom_attributes.push(KeyValue::new( - APOLLO_PRIVATE_COST_ACTUAL.clone(), - AttributeValue::I64(cost.actual as i64), - )); - custom_attributes.push(KeyValue::new( - APOLLO_PRIVATE_COST_RESULT.clone(), - AttributeValue::String(cost.result.into()), - )); - custom_attributes.push(KeyValue::new( - APOLLO_PRIVATE_COST_STRATEGY.clone(), - AttributeValue::String(cost.strategy.into()), - )); - } - }); -} - impl Telemetry { pub(crate) fn activate(&self) { let mut activation = self.activation.lock(); From 64e3e42135013aa8040829f3901435854cc735ad Mon Sep 17 00:00:00 2001 From: bryn Date: Thu, 13 Jun 2024 17:39:24 +0100 Subject: [PATCH 4/8] Lint --- apollo-router/src/plugins/telemetry/config_new/cost/mod.rs | 3 ++- .../src/plugins/telemetry/tracing/apollo_telemetry.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs b/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs index 6402f86787..8ad933e3a7 100644 --- a/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs +++ b/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs @@ -1,7 +1,8 @@ use std::sync::Arc; use opentelemetry::metrics::MeterProvider; -use opentelemetry_api::{Key, KeyValue}; +use opentelemetry_api::Key; +use opentelemetry_api::KeyValue; use parking_lot::Mutex; use schemars::JsonSchema; use serde::Deserialize; diff --git a/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs b/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs index 4f210eebbc..0a6e038999 100644 --- a/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs +++ b/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs @@ -53,9 +53,10 @@ use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::query_pla use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::query_plan_node::ParallelNode; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::query_plan_node::ResponsePathElement; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::query_plan_node::SequenceNode; +use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::Details; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::Http; +use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::Limits; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::QueryPlanNode; -use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::{Details, Limits}; use crate::plugins::telemetry::apollo_exporter::ApolloExporter; use crate::plugins::telemetry::apollo_otlp_exporter::ApolloOtlpExporter; use crate::plugins::telemetry::config::Sampler; From a6b7e232f7a272d23d92a494fff4fbbaff03af72 Mon Sep 17 00:00:00 2001 From: bryn Date: Thu, 13 Jun 2024 18:11:42 +0100 Subject: [PATCH 5/8] Lint --- apollo-router/tests/apollo_reports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apollo-router/tests/apollo_reports.rs b/apollo-router/tests/apollo_reports.rs index 11a1288273..e183f29dc8 100644 --- a/apollo-router/tests/apollo_reports.rs +++ b/apollo-router/tests/apollo_reports.rs @@ -675,7 +675,7 @@ async fn test_demand_control_trace_batched() { result.push(b']'); hyper::Body::from(result) }); - let req: router::Request = request.try_into().expect("could not convert request"); + let req: router::Request = request.into(); let reports = Arc::new(Mutex::new(vec![])); let report = get_batch_trace_report(reports, req, use_legacy_request_span, true).await; assert_report!(report); From 9b1d0468893c0da0c145c5e0cbc4c29c3a7b0760 Mon Sep 17 00:00:00 2001 From: bryn Date: Thu, 13 Jun 2024 18:15:22 +0100 Subject: [PATCH 6/8] Changelog --- .changesets/maint_bryn_demand_control_studio_traces.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changesets/maint_bryn_demand_control_studio_traces.md diff --git a/.changesets/maint_bryn_demand_control_studio_traces.md b/.changesets/maint_bryn_demand_control_studio_traces.md new file mode 100644 index 0000000000..d429855852 --- /dev/null +++ b/.changesets/maint_bryn_demand_control_studio_traces.md @@ -0,0 +1,5 @@ +### Add cost information to protobuf traces ([PR #5430](https://github.com/apollographql/router/pull/5430)) + +If `experimental_demand_control` is enabled, cost information for queries is now exported on Apollo protobuf traces for display in studio. + +By [@BrynCooke](https://github.com/BrynCooke) in https://github.com/apollographql/router/pull/5430 From 1122d55139abd18589bc285ab54aa4a9fbbd3860 Mon Sep 17 00:00:00 2001 From: bryn Date: Fri, 14 Jun 2024 09:38:16 +0100 Subject: [PATCH 7/8] Always populate limits on traces. Add test for extraction --- .../plugins/telemetry/config_new/cost/mod.rs | 4 +- .../telemetry/tracing/apollo_telemetry.rs | 111 ++++++++++++------ .../apollo_reports__batch_send_header.snap | 20 +++- .../apollo_reports__batch_trace_id.snap | 20 +++- .../apollo_reports__client_name.snap | 10 +- .../apollo_reports__client_version.snap | 10 +- .../apollo_reports__condition_else.snap | 10 +- .../apollo_reports__condition_if.snap | 10 +- .../snapshots/apollo_reports__non_defer.snap | 10 +- .../apollo_reports__send_header.snap | 10 +- .../apollo_reports__send_variable_value.snap | 10 +- .../snapshots/apollo_reports__trace_id.snap | 10 +- 12 files changed, 183 insertions(+), 52 deletions(-) diff --git a/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs b/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs index 8ad933e3a7..43eb31948a 100644 --- a/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs +++ b/apollo-router/src/plugins/telemetry/config_new/cost/mod.rs @@ -287,11 +287,11 @@ pub(crate) fn add_cost_attributes(context: &Context, custom_attributes: &mut Vec if let Some(cost) = c.get::().cloned() { custom_attributes.push(KeyValue::new( APOLLO_PRIVATE_COST_ESTIMATED.clone(), - AttributeValue::I64(cost.estimated as i64), + AttributeValue::F64(cost.estimated), )); custom_attributes.push(KeyValue::new( APOLLO_PRIVATE_COST_ACTUAL.clone(), - AttributeValue::I64(cost.actual as i64), + AttributeValue::F64(cost.actual), )); custom_attributes.push(KeyValue::new( APOLLO_PRIVATE_COST_RESULT.clone(), diff --git a/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs b/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs index 0a6e038999..578da298cf 100644 --- a/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs +++ b/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs @@ -588,35 +588,6 @@ impl Exporter { )] } SUPERGRAPH_SPAN_NAME => { - let limits = span - .attributes - .get(&APOLLO_PRIVATE_COST_RESULT) - .and_then(extract_string) - .map(|result| { - Limits { - result, - strategy: span - .attributes - .get(&APOLLO_PRIVATE_COST_STRATEGY) - .and_then(extract_string) - .unwrap_or_default(), - cost_estimated: span - .attributes - .get(&APOLLO_PRIVATE_COST_ESTIMATED) - .and_then(extract_u64) - .unwrap_or_default(), - cost_actual: span - .attributes - .get(&APOLLO_PRIVATE_COST_ACTUAL) - .and_then(extract_u64) - .unwrap_or_default(), - // Not extracted yet - depth: 0, - height: 0, - alias_count: 0, - root_field_count: 0, - } - }); //Currently some data is in the supergraph span as we don't have the a request hook in plugin. child_nodes.push(TreeData::Supergraph { operation_signature: span @@ -634,7 +605,7 @@ impl Exporter { .get(&APOLLO_PRIVATE_GRAPHQL_VARIABLES) .and_then(extract_json) .unwrap_or_default(), - limits, + limits: Some(extract_limits(span)), }); child_nodes } @@ -816,6 +787,36 @@ impl Exporter { } } +fn extract_limits(span: &LightSpanData) -> Limits { + Limits { + result: span + .attributes + .get(&APOLLO_PRIVATE_COST_RESULT) + .and_then(extract_string) + .unwrap_or_default(), + strategy: span + .attributes + .get(&APOLLO_PRIVATE_COST_STRATEGY) + .and_then(extract_string) + .unwrap_or_default(), + cost_estimated: span + .attributes + .get(&APOLLO_PRIVATE_COST_ESTIMATED) + .and_then(extract_f64) + .unwrap_or_default() as u64, + cost_actual: span + .attributes + .get(&APOLLO_PRIVATE_COST_ACTUAL) + .and_then(extract_f64) + .unwrap_or_default() as u64, + // TODO fill these out + depth: 0, + height: 0, + alias_count: 0, + root_field_count: 0, + } +} + fn extract_json(v: &Value) -> Option { extract_string(v) .map(|v| serde_json::from_str(&v)) @@ -868,13 +869,9 @@ pub(crate) fn extract_i64(v: &Value) -> Option { } } -pub(crate) fn extract_u64(v: &Value) -> Option { - if let Value::I64(v) = v { - if *v > 0 { - Some(*v as u64) - } else { - None - } +pub(crate) fn extract_f64(v: &Value) -> Option { + if let Value::F64(v) = v { + Some(*v) } else { None } @@ -1195,14 +1192,18 @@ impl ChildNodes for Vec { #[cfg(test)] mod test { + use std::time::SystemTime; use opentelemetry::Value; + use opentelemetry_api::KeyValue; + use opentelemetry_api::trace::{SpanId, SpanKind, TraceId}; + use opentelemetry_sdk::trace::EvictedHashMap; use serde_json::json; use crate::plugins::telemetry::apollo::ErrorConfiguration; use crate::plugins::telemetry::apollo_exporter::proto::reports::Trace; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::query_plan_node::{DeferNodePrimary, DeferredNode, ResponsePathElement}; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::{QueryPlanNode, Node, Error}; use crate::plugins::telemetry::apollo_exporter::proto::reports::trace::query_plan_node::response_path_element::Id; - use crate::plugins::telemetry::tracing::apollo_telemetry::{extract_ftv1_trace, extract_ftv1_trace_with_error_count, extract_i64, extract_json, extract_path, extract_string, preprocess_errors, encode_ftv1_trace, ChildNodes, TreeData}; + use crate::plugins::telemetry::tracing::apollo_telemetry::{extract_ftv1_trace, extract_ftv1_trace_with_error_count, extract_i64, extract_json, extract_path, extract_string, preprocess_errors, encode_ftv1_trace, ChildNodes, TreeData, LightSpanData, APOLLO_PRIVATE_COST_RESULT, APOLLO_PRIVATE_COST_ESTIMATED, APOLLO_PRIVATE_COST_ACTUAL, APOLLO_PRIVATE_COST_STRATEGY, extract_limits}; fn elements(tree_data: Vec) -> Vec<&'static str> { let mut elements = Vec::new(); @@ -1543,4 +1544,38 @@ mod test { assert!(node.error.is_empty()); assert!(node.child[0].error.is_empty()); } + + #[test] + fn test_extract_limits() { + let mut span = LightSpanData { + trace_id: TraceId::from_u128(0), + span_id: SpanId::from_u64(1), + parent_span_id: SpanId::INVALID, + span_kind: SpanKind::Client, + name: Default::default(), + start_time: SystemTime::now(), + end_time: SystemTime::now(), + attributes: EvictedHashMap::new(10, 10), + status: Default::default(), + }; + + span.attributes.insert(KeyValue::new( + APOLLO_PRIVATE_COST_RESULT, + Value::String("OK".into()), + )); + span.attributes.insert(KeyValue::new( + APOLLO_PRIVATE_COST_ESTIMATED, + Value::F64(9.2), + )); + span.attributes + .insert(KeyValue::new(APOLLO_PRIVATE_COST_ACTUAL, Value::F64(6.9))); + span.attributes.insert(KeyValue::new( + APOLLO_PRIVATE_COST_STRATEGY, + Value::String("static_estimated".into()), + )); + let limits = extract_limits(&span); + assert_eq!(limits.result, "OK"); + assert_eq!(limits.cost_estimated, 9); + assert_eq!(limits.cost_actual, 6); + } } diff --git a/apollo-router/tests/snapshots/apollo_reports__batch_send_header.snap b/apollo-router/tests/snapshots/apollo_reports__batch_send_header.snap index 15c2327c19..760e662f56 100644 --- a/apollo-router/tests/snapshots/apollo_reports__batch_send_header.snap +++ b/apollo-router/tests/snapshots/apollo_reports__batch_send_header.snap @@ -552,7 +552,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 - start_time: seconds: "[seconds]" nanos: "[nanos]" @@ -1092,7 +1100,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__batch_trace_id.snap b/apollo-router/tests/snapshots/apollo_reports__batch_trace_id.snap index e152be5676..f7c1ad4188 100644 --- a/apollo-router/tests/snapshots/apollo_reports__batch_trace_id.snap +++ b/apollo-router/tests/snapshots/apollo_reports__batch_trace_id.snap @@ -549,7 +549,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 - start_time: seconds: "[seconds]" nanos: "[nanos]" @@ -1086,7 +1094,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__client_name.snap b/apollo-router/tests/snapshots/apollo_reports__client_name.snap index cdd69f128b..c05170f09e 100644 --- a/apollo-router/tests/snapshots/apollo_reports__client_name.snap +++ b/apollo-router/tests/snapshots/apollo_reports__client_name.snap @@ -549,7 +549,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__client_version.snap b/apollo-router/tests/snapshots/apollo_reports__client_version.snap index 3e0f375077..aecb5e78fe 100644 --- a/apollo-router/tests/snapshots/apollo_reports__client_version.snap +++ b/apollo-router/tests/snapshots/apollo_reports__client_version.snap @@ -549,7 +549,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__condition_else.snap b/apollo-router/tests/snapshots/apollo_reports__condition_else.snap index bb048564c8..1a3748a9c6 100644 --- a/apollo-router/tests/snapshots/apollo_reports__condition_else.snap +++ b/apollo-router/tests/snapshots/apollo_reports__condition_else.snap @@ -555,7 +555,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__condition_if.snap b/apollo-router/tests/snapshots/apollo_reports__condition_if.snap index 2e45b53a67..a043c1c333 100644 --- a/apollo-router/tests/snapshots/apollo_reports__condition_if.snap +++ b/apollo-router/tests/snapshots/apollo_reports__condition_if.snap @@ -568,7 +568,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__non_defer.snap b/apollo-router/tests/snapshots/apollo_reports__non_defer.snap index 16c6d72247..b36f7341ee 100644 --- a/apollo-router/tests/snapshots/apollo_reports__non_defer.snap +++ b/apollo-router/tests/snapshots/apollo_reports__non_defer.snap @@ -549,7 +549,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__send_header.snap b/apollo-router/tests/snapshots/apollo_reports__send_header.snap index d4cc1e50f9..448af827a8 100644 --- a/apollo-router/tests/snapshots/apollo_reports__send_header.snap +++ b/apollo-router/tests/snapshots/apollo_reports__send_header.snap @@ -552,7 +552,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__send_variable_value.snap b/apollo-router/tests/snapshots/apollo_reports__send_variable_value.snap index 9bd1bcf5c4..31c50d581c 100644 --- a/apollo-router/tests/snapshots/apollo_reports__send_variable_value.snap +++ b/apollo-router/tests/snapshots/apollo_reports__send_variable_value.snap @@ -551,7 +551,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__trace_id.snap b/apollo-router/tests/snapshots/apollo_reports__trace_id.snap index 16c6d72247..b36f7341ee 100644 --- a/apollo-router/tests/snapshots/apollo_reports__trace_id.snap +++ b/apollo-router/tests/snapshots/apollo_reports__trace_id.snap @@ -549,7 +549,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ From 840fd592813b5c79879cc421b3cf0c517208645a Mon Sep 17 00:00:00 2001 From: bryn Date: Fri, 14 Jun 2024 10:49:39 +0100 Subject: [PATCH 8/8] Update snapshots --- .../apollo_reports__batch_send_header-2.snap | 20 +++++++++++++++++-- .../apollo_reports__batch_trace_id-2.snap | 20 +++++++++++++++++-- .../apollo_reports__client_name-2.snap | 10 +++++++++- .../apollo_reports__client_version-2.snap | 10 +++++++++- .../apollo_reports__condition_else-2.snap | 10 +++++++++- .../apollo_reports__condition_if-2.snap | 10 +++++++++- .../apollo_reports__non_defer-2.snap | 10 +++++++++- .../apollo_reports__send_header-2.snap | 10 +++++++++- ...apollo_reports__send_variable_value-2.snap | 10 +++++++++- .../snapshots/apollo_reports__trace_id-2.snap | 10 +++++++++- 10 files changed, 108 insertions(+), 12 deletions(-) diff --git a/apollo-router/tests/snapshots/apollo_reports__batch_send_header-2.snap b/apollo-router/tests/snapshots/apollo_reports__batch_send_header-2.snap index 15c2327c19..760e662f56 100644 --- a/apollo-router/tests/snapshots/apollo_reports__batch_send_header-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__batch_send_header-2.snap @@ -552,7 +552,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 - start_time: seconds: "[seconds]" nanos: "[nanos]" @@ -1092,7 +1100,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__batch_trace_id-2.snap b/apollo-router/tests/snapshots/apollo_reports__batch_trace_id-2.snap index e152be5676..f7c1ad4188 100644 --- a/apollo-router/tests/snapshots/apollo_reports__batch_trace_id-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__batch_trace_id-2.snap @@ -549,7 +549,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 - start_time: seconds: "[seconds]" nanos: "[nanos]" @@ -1086,7 +1094,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__client_name-2.snap b/apollo-router/tests/snapshots/apollo_reports__client_name-2.snap index cdd69f128b..c05170f09e 100644 --- a/apollo-router/tests/snapshots/apollo_reports__client_name-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__client_name-2.snap @@ -549,7 +549,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__client_version-2.snap b/apollo-router/tests/snapshots/apollo_reports__client_version-2.snap index 3e0f375077..aecb5e78fe 100644 --- a/apollo-router/tests/snapshots/apollo_reports__client_version-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__client_version-2.snap @@ -549,7 +549,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__condition_else-2.snap b/apollo-router/tests/snapshots/apollo_reports__condition_else-2.snap index bb048564c8..1a3748a9c6 100644 --- a/apollo-router/tests/snapshots/apollo_reports__condition_else-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__condition_else-2.snap @@ -555,7 +555,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__condition_if-2.snap b/apollo-router/tests/snapshots/apollo_reports__condition_if-2.snap index 2e45b53a67..a043c1c333 100644 --- a/apollo-router/tests/snapshots/apollo_reports__condition_if-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__condition_if-2.snap @@ -568,7 +568,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__non_defer-2.snap b/apollo-router/tests/snapshots/apollo_reports__non_defer-2.snap index 16c6d72247..b36f7341ee 100644 --- a/apollo-router/tests/snapshots/apollo_reports__non_defer-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__non_defer-2.snap @@ -549,7 +549,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__send_header-2.snap b/apollo-router/tests/snapshots/apollo_reports__send_header-2.snap index d4cc1e50f9..448af827a8 100644 --- a/apollo-router/tests/snapshots/apollo_reports__send_header-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__send_header-2.snap @@ -552,7 +552,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__send_variable_value-2.snap b/apollo-router/tests/snapshots/apollo_reports__send_variable_value-2.snap index 9bd1bcf5c4..31c50d581c 100644 --- a/apollo-router/tests/snapshots/apollo_reports__send_variable_value-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__send_variable_value-2.snap @@ -551,7 +551,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~ diff --git a/apollo-router/tests/snapshots/apollo_reports__trace_id-2.snap b/apollo-router/tests/snapshots/apollo_reports__trace_id-2.snap index 16c6d72247..b36f7341ee 100644 --- a/apollo-router/tests/snapshots/apollo_reports__trace_id-2.snap +++ b/apollo-router/tests/snapshots/apollo_reports__trace_id-2.snap @@ -549,7 +549,15 @@ traces_per_query: registered_operation: false forbidden_operation: false field_execution_weight: 1 - limits: ~ + limits: + result: "" + strategy: "" + cost_estimated: 0 + cost_actual: 0 + depth: 0 + height: 0 + alias_count: 0 + root_field_count: 0 stats_with_context: [] referenced_fields_by_type: {} query_metadata: ~