diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index 88956f16cf..19abfa8f58 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -238,6 +238,12 @@ supergraph: By [@Geal](https://github.com/Geal) in https://github.com/apollographql/router/pull/2155 +### `@defer` Apollo tracing support ([Issue #1600](https://github.com/apollographql/router/issues/1600)) + +Added Apollo tracing support for queries that use `@defer`. You can now view traces in Apollo Studio as normal. + +By [@bryncooke](https://github.com/bryncooke) in https://github.com/apollographql/router/pull/2190 + ## 🐛 Fixes ### Fix panic when dev mode enabled with empty config file ([Issue #2182](https://github.com/apollographql/router/issues/2182)) @@ -246,6 +252,18 @@ If you're running the Router with dev mode with an empty config file, it will no By [@bnjjj](https://github.com/bnjjj) in https://github.com/apollographql/router/pull/2165 +### Fix missing apollo tracing variables ([Issue #2186](https://github.com/apollographql/router/issues/2186)) + +Send variable values had no effect. This is now fixed. +```yaml +telemetry: + apollo: + send_variable_values: all +``` + +By [@bryncooke](https://github.com/bryncooke) in https://github.com/apollographql/router/pull/2190 + + ### fix build_docker_image.sh script when using default repo ([PR #2163](https://github.com/apollographql/router/pull/2163)) Adding the `-r` flag recently broke the existing functionality to build from the default repo using `-b`. This fixes that. diff --git a/apollo-router/Cargo.toml b/apollo-router/Cargo.toml index 680e383837..4b4fd1d7de 100644 --- a/apollo-router/Cargo.toml +++ b/apollo-router/Cargo.toml @@ -202,7 +202,7 @@ uname = "0.1.1" uname = "0.1.1" [dev-dependencies] -insta = { version = "1.21.2", features = ["json", "redactions"] } +insta = { version = "1.21.2", features = ["json", "redactions", "yaml"] } introspector-gadget = "0.1.0" maplit = "1.0.2" memchr = { version = "2.5.0", default-features = false } diff --git a/apollo-router/src/plugins/telemetry/apollo_exporter.rs b/apollo-router/src/plugins/telemetry/apollo_exporter.rs index 8392ae2781..2028b667c1 100644 --- a/apollo-router/src/plugins/telemetry/apollo_exporter.rs +++ b/apollo-router/src/plugins/telemetry/apollo_exporter.rs @@ -1,4 +1,8 @@ //! Configuration for apollo telemetry exporter. +#[cfg(test)] +use std::sync::Arc; +#[cfg(test)] +use std::sync::Mutex; // This entire file is license key functionality use std::time::Duration; @@ -31,20 +35,26 @@ pub(crate) const POOL_TIMEOUT: Duration = Duration::from_secs(5); pub(crate) enum Sender { Noop, Spaceport(mpsc::Sender), + #[cfg(test)] + InMemory(Arc>>), } impl Sender { - pub(crate) fn send(&self, metrics: SingleReport) { + pub(crate) fn send(&self, report: SingleReport) { match &self { Sender::Noop => {} Sender::Spaceport(channel) => { - if let Err(err) = channel.to_owned().try_send(metrics) { + if let Err(err) = channel.to_owned().try_send(report) { tracing::warn!( "could not send metrics to spaceport, metric will be dropped: {}", err ); } } + #[cfg(test)] + Sender::InMemory(storage) => { + storage.lock().expect("mutex poisoned").push(report); + } } } } diff --git a/apollo-router/src/plugins/telemetry/mod.rs b/apollo-router/src/plugins/telemetry/mod.rs index 33295f8d1c..7aae5c34e9 100644 --- a/apollo-router/src/plugins/telemetry/mod.rs +++ b/apollo-router/src/plugins/telemetry/mod.rs @@ -122,7 +122,6 @@ const CLIENT_VERSION: &str = "apollo_telemetry::client_version"; const ATTRIBUTES: &str = "apollo_telemetry::metrics_attributes"; const SUBGRAPH_ATTRIBUTES: &str = "apollo_telemetry::subgraph_metrics_attributes"; pub(crate) const STUDIO_EXCLUDE: &str = "apollo_telemetry::studio::exclude"; -pub(crate) const FTV1_DO_NOT_SAMPLE: &str = "apollo_telemetry::studio::ftv1_do_not_sample"; pub(crate) const LOGGING_DISPLAY_HEADERS: &str = "apollo_telemetry::logging::display_headers"; pub(crate) const LOGGING_DISPLAY_BODY: &str = "apollo_telemetry::logging::display_body"; const DEFAULT_SERVICE_NAME: &str = "apollo-router"; @@ -280,31 +279,9 @@ impl Plugin for Telemetry { fn execution_service(&self, service: execution::BoxService) -> execution::BoxService { ServiceBuilder::new() - .instrument(move |req: &ExecutionRequest| { - // disable ftv1 sampling for deferred queries - let do_not_sample_reason = if req.query_plan.root.contains_condition_or_defer() { - req.context.insert(FTV1_DO_NOT_SAMPLE, true).unwrap(); - "query is deferred" - } else { - "" - }; - let query = req - .supergraph_request - .body() - .query - .clone() - .unwrap_or_default(); - let operation_name = req - .supergraph_request - .body() - .operation_name - .clone() - .unwrap_or_default(); + .instrument(move |_req: &ExecutionRequest| { info_span!("execution", - graphql.document = query.as_str(), - graphql.operation.name = operation_name.as_str(), "otel.kind" = %SpanKind::Internal, - ftv1.do_not_sample_reason = do_not_sample_reason ) }) .service(service) @@ -707,7 +684,7 @@ impl Telemetry { apollo_private.http.request_headers = field::Empty ); - if is_span_sampled(&request.context) { + if is_span_sampled() { span.record( "apollo_private.graphql.variables", &Self::filter_variables_values( @@ -792,7 +769,7 @@ impl Telemetry { } }) .fold(BTreeMap::new(), |mut acc, (name, value)| { - acc.entry(name).or_insert_with(Vec::new).push(value); + acc.insert(name, value); acc }); @@ -1185,7 +1162,7 @@ impl Telemetry { has_errors: bool, duration: Duration, ) { - if is_span_sampled(context) { + if is_span_sampled() { ::tracing::trace!("span is sampled then skip the apollo metrics"); return; } @@ -1294,12 +1271,8 @@ fn handle_error>(err: T) { } #[inline] -pub(crate) fn is_span_sampled(context: &Context) -> bool { +pub(crate) fn is_span_sampled() -> bool { Span::current().context().span().span_context().is_sampled() - && !context - .get(FTV1_DO_NOT_SAMPLE) - .unwrap_or_default() - .unwrap_or(false) } register_plugin!("apollo", "telemetry", Telemetry); @@ -1315,7 +1288,7 @@ enum ApolloFtv1Handler { impl ApolloFtv1Handler { fn request_ftv1(&self, mut req: SubgraphRequest) -> SubgraphRequest { if let ApolloFtv1Handler::Enabled = self { - if is_span_sampled(&req.context) { + if is_span_sampled() { req.subgraph_request.headers_mut().insert( "apollo-federation-include-trace", HeaderValue::from_static("ftv1"), diff --git a/apollo-router/src/plugins/telemetry/tracing/apollo.rs b/apollo-router/src/plugins/telemetry/tracing/apollo.rs index 969c1a2247..46ddbb785a 100644 --- a/apollo-router/src/plugins/telemetry/tracing/apollo.rs +++ b/apollo-router/src/plugins/telemetry/tracing/apollo.rs @@ -11,7 +11,7 @@ use crate::plugins::telemetry::tracing::TracingConfigurator; use crate::spaceport::Trace; impl TracingConfigurator for Config { - fn apply(&self, builder: Builder, trace_config: &config::Trace) -> Result { + fn apply(&self, builder: Builder, _trace_config: &config::Trace) -> Result { tracing::debug!("configuring Apollo tracing"); Ok(match self { Config { @@ -28,7 +28,6 @@ impl TracingConfigurator for Config { let exporter = apollo_telemetry::Exporter::builder() .expose_trace_id_config(expose_trace_id.clone()) - .trace_config(trace_config.clone()) .endpoint(endpoint.clone()) .apollo_key(key) .apollo_graph_ref(reference) diff --git a/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs b/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs index c8cddba186..9ed26f161a 100644 --- a/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs +++ b/apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs @@ -1,10 +1,10 @@ -use std::borrow::Cow; use std::collections::HashMap; use std::io::Cursor; use std::time::SystemTimeError; use async_trait::async_trait; use derivative::Derivative; +use itertools::Itertools; use lru::LruCache; use opentelemetry::sdk::export::trace::ExportResult; use opentelemetry::sdk::export::trace::SpanData; @@ -13,6 +13,7 @@ use opentelemetry::trace::SpanId; use opentelemetry::Key; use opentelemetry::Value; use opentelemetry_semantic_conventions::trace::HTTP_METHOD; +use serde::de::DeserializeOwned; use thiserror::Error; use url::Url; @@ -21,17 +22,29 @@ use crate::plugins::telemetry::apollo::SingleReport; use crate::plugins::telemetry::apollo_exporter::ApolloExporter; use crate::plugins::telemetry::apollo_exporter::Sender; use crate::plugins::telemetry::config; +use crate::plugins::telemetry::config::ExposeTraceId; use crate::plugins::telemetry::config::Sampler; use crate::plugins::telemetry::config::SamplerOption; use crate::plugins::telemetry::tracing::apollo::TracesReport; use crate::plugins::telemetry::BoxError; use crate::plugins::telemetry::SUBGRAPH_SPAN_NAME; use crate::plugins::telemetry::SUPERGRAPH_SPAN_NAME; +use crate::query_planner::CONDITION_ELSE_SPAN_NAME; +use crate::query_planner::CONDITION_IF_SPAN_NAME; +use crate::query_planner::CONDITION_SPAN_NAME; +use crate::query_planner::DEFER_DEFERRED_SPAN_NAME; +use crate::query_planner::DEFER_PRIMARY_SPAN_NAME; +use crate::query_planner::DEFER_SPAN_NAME; use crate::query_planner::FETCH_SPAN_NAME; use crate::query_planner::FLATTEN_SPAN_NAME; use crate::query_planner::PARALLEL_SPAN_NAME; use crate::query_planner::SEQUENCE_SPAN_NAME; use crate::spaceport::trace::http::Values; +use crate::spaceport::trace::query_plan_node::ConditionNode; +use crate::spaceport::trace::query_plan_node::DeferNode; +use crate::spaceport::trace::query_plan_node::DeferNodePrimary; +use crate::spaceport::trace::query_plan_node::DeferredNode; +use crate::spaceport::trace::query_plan_node::DeferredNodeDepends; use crate::spaceport::trace::query_plan_node::FetchNode; use crate::spaceport::trace::query_plan_node::FlattenNode; use crate::spaceport::trace::query_plan_node::ParallelNode; @@ -52,11 +65,14 @@ const APOLLO_PRIVATE_HTTP_REQUEST_HEADERS: Key = pub(crate) const APOLLO_PRIVATE_OPERATION_SIGNATURE: Key = Key::from_static_str("apollo_private.operation_signature"); const APOLLO_PRIVATE_FTV1: Key = Key::from_static_str("apollo_private.ftv1"); -const APOLLO_PRIVATE_PATH: Key = Key::from_static_str("apollo_private.path"); -const FTV1_DO_NOT_SAMPLE_REASON: Key = Key::from_static_str("ftv1.do_not_sample_reason"); +const PATH: Key = Key::from_static_str("graphql.path"); const SUBGRAPH_NAME: Key = Key::from_static_str("apollo.subgraph.name"); const CLIENT_NAME: Key = Key::from_static_str("client.name"); const CLIENT_VERSION: Key = Key::from_static_str("client.version"); +const DEPENDS: Key = Key::from_static_str("graphql.depends"); +const LABEL: Key = Key::from_static_str("graphql.label"); +const CONDITION: Key = Key::from_static_str("graphql.condition"); +const OPERATION_NAME: Key = Key::from_static_str("graphql.operation.name"); pub(crate) const DEFAULT_TRACE_ID_HEADER_NAME: &str = "apollo-trace-id"; #[derive(Error, Debug)] @@ -67,17 +83,14 @@ pub(crate) enum Error { #[error("subgraph trace payload was not base64")] Base64Decode(#[from] base64::DecodeError), - #[error("ftv1 span attribute should have been a string")] - Ftv1SpanAttribute, + #[error("trace parsing failed")] + TraceParsingFailed, #[error("there were multiple tracing errors")] MultipleErrors(Vec), #[error("duration could not be calculated")] SystemTime(#[from] SystemTimeError), - - #[error("this trace should not be sampled")] - DoNotSample(Cow<'static, str>), } /// A [`SpanExporter`] that writes to [`Reporter`]. @@ -88,10 +101,7 @@ pub(crate) enum Error { #[derivative(Debug)] pub(crate) struct Exporter { expose_trace_id_config: config::ExposeTraceId, - trace_config: config::Trace, spans_by_parent_id: LruCache>, - endpoint: Url, - schema_id: String, #[derivative(Debug = "ignore")] apollo_sender: Sender, field_execution_weight: f64, @@ -104,9 +114,15 @@ enum TreeData { client_name: Option, client_version: Option, operation_signature: String, + operation_name: String, + variables_json: HashMap, }, - QueryPlan(QueryPlanNode), - Trace(Result>, Error>), + QueryPlanNode(QueryPlanNode), + DeferPrimary(DeferNodePrimary), + DeferDeferred(DeferredNode), + ConditionIf(Option), + ConditionElse(Option), + Trace(Option, Error>>), } #[buildstructor::buildstructor] @@ -114,7 +130,6 @@ impl Exporter { #[builder] pub(crate) fn new( expose_trace_id_config: config::ExposeTraceId, - trace_config: config::Trace, endpoint: Url, apollo_key: String, apollo_graph_ref: String, @@ -128,9 +143,6 @@ impl Exporter { Ok(Self { expose_trace_id_config, spans_by_parent_id: LruCache::new(buffer_size), - trace_config, - endpoint, - schema_id, apollo_sender: apollo_exporter.provider(), field_execution_weight: match field_execution_sampler { Some(SamplerOption::Always(Sampler::AlwaysOn)) => 1.0, @@ -146,23 +158,7 @@ impl Exporter { span: &SpanData, child_nodes: Vec, ) -> Result, Error> { - let variables = span - .attributes - .get(&APOLLO_PRIVATE_GRAPHQL_VARIABLES) - .map(|data| data.as_str()) - .unwrap_or_default(); - let variables_json = if variables != "{}" { - serde_json::from_str(&variables).unwrap_or_default() - } else { - HashMap::new() - }; - - let details = Details { - variables_json, - ..Default::default() - }; - - let http = self.extract_http_data(span); + let http = extract_http_data(span, &self.expose_trace_id_config); let mut root_trace = crate::spaceport::Trace { start_time: Some(span.start_time.into()), @@ -170,18 +166,18 @@ impl Exporter { duration_ns: span .attributes .get(&APOLLO_PRIVATE_DURATION_NS) - .and_then(Self::extract_i64) + .and_then(extract_i64) .map(|e| e as u64) .unwrap_or_default(), root: None, - details: Some(details), + details: None, http: Some(http), ..Default::default() }; for node in child_nodes { match node { - TreeData::QueryPlan(query_plan) => { + TreeData::QueryPlanNode(query_plan) => { root_trace.query_plan = Some(Box::new(query_plan)) } TreeData::Supergraph { @@ -189,6 +185,8 @@ impl Exporter { client_name, client_version, operation_signature, + operation_name, + variables_json, } => { root_trace .http @@ -198,8 +196,11 @@ impl Exporter { root_trace.client_name = client_name.unwrap_or_default(); root_trace.client_version = client_version.unwrap_or_default(); root_trace.field_execution_weight = self.field_execution_weight; - // This will be moved out later root_trace.signature = operation_signature; + root_trace.details = Some(Details { + variables_json, + operation_name, + }); } _ => panic!("should never have had other node types"), } @@ -243,43 +244,26 @@ impl Exporter { if !errors.is_empty() { return Err(Error::MultipleErrors(errors)); } - if let Some(Value::String(reason)) = span.attributes.get(&FTV1_DO_NOT_SAMPLE_REASON) { - if !reason.is_empty() { - return Err(Error::DoNotSample(reason.clone())); - } - } Ok(match span.name.as_ref() { - PARALLEL_SPAN_NAME => vec![TreeData::QueryPlan(QueryPlanNode { + PARALLEL_SPAN_NAME => vec![TreeData::QueryPlanNode(QueryPlanNode { node: Some(crate::spaceport::trace::query_plan_node::Node::Parallel( ParallelNode { - nodes: child_nodes - .into_iter() - .filter_map(|child| match child { - TreeData::QueryPlan(node) => Some(node), - _ => None, - }) - .collect(), + nodes: child_nodes.remove_query_plan_nodes(), }, )), })], - SEQUENCE_SPAN_NAME => vec![TreeData::QueryPlan(QueryPlanNode { + SEQUENCE_SPAN_NAME => vec![TreeData::QueryPlanNode(QueryPlanNode { node: Some(crate::spaceport::trace::query_plan_node::Node::Sequence( SequenceNode { - nodes: child_nodes - .into_iter() - .filter_map(|child| match child { - TreeData::QueryPlan(node) => Some(node), - _ => None, - }) - .collect(), + nodes: child_nodes.remove_query_plan_nodes(), }, )), })], FETCH_SPAN_NAME => { let (trace_parsing_failed, trace) = match child_nodes.pop() { - Some(TreeData::Trace(Ok(trace))) => (false, trace), - Some(TreeData::Trace(Err(_err))) => (true, None), + Some(TreeData::Trace(Some(Ok(trace)))) => (false, Some(trace)), + Some(TreeData::Trace(Some(Err(_err)))) => (true, None), _ => (false, None), }; let service_name = (span @@ -289,7 +273,7 @@ impl Exporter { .unwrap_or_else(|| Value::String("unknown service".into())) .as_str()) .to_string(); - vec![TreeData::QueryPlan(QueryPlanNode { + vec![TreeData::QueryPlanNode(QueryPlanNode { node: Some(crate::spaceport::trace::query_plan_node::Node::Fetch( Box::new(FetchNode { service_name, @@ -298,7 +282,7 @@ impl Exporter { sent_time_offset: span .attributes .get(&APOLLO_PRIVATE_SENT_TIME_OFFSET) - .and_then(Self::extract_i64) + .and_then(extract_i64) .map(|f| f as u64) .unwrap_or_default(), sent_time: Some(span.start_time.into()), @@ -308,52 +292,49 @@ impl Exporter { })] } FLATTEN_SPAN_NAME => { - vec![TreeData::QueryPlan(QueryPlanNode { + vec![TreeData::QueryPlanNode(QueryPlanNode { node: Some(crate::spaceport::trace::query_plan_node::Node::Flatten( Box::new(FlattenNode { response_path: span .attributes - .get(&APOLLO_PRIVATE_PATH) - .and_then(Self::extract_string) - .map(|v| { - v.split('/').filter(|v|!v.is_empty() && *v != "@").map(|v| { - if let Ok(index) = v.parse::() { - ResponsePathElement { id: Some(crate::spaceport::trace::query_plan_node::response_path_element::Id::Index(index))} - } else { - ResponsePathElement { id: Some(crate::spaceport::trace::query_plan_node::response_path_element::Id::FieldName(v.to_string())) } - } - }).collect() - }).unwrap_or_default(), - node: child_nodes - .into_iter() - .filter_map(|child| match child { - TreeData::QueryPlan(node) => Some(Box::new(node)), - _ => None, - }) - .next(), + .get(&PATH) + .map(extract_path) + .unwrap_or_default(), + node: child_nodes.remove_first_query_plan_node().map(Box::new), }), )), })] } SUBGRAPH_SPAN_NAME => { - vec![TreeData::Trace(self.find_ftv1_trace(span))] + vec![TreeData::Trace( + span.attributes + .get(&APOLLO_PRIVATE_FTV1) + .and_then(extract_ftv1_trace), + )] } SUPERGRAPH_SPAN_NAME => { //Currently some data is in the supergraph span as we don't have the a request hook in plugin. child_nodes.push(TreeData::Supergraph { - http: self.extract_http_data(span), - client_name: span - .attributes - .get(&CLIENT_NAME) - .and_then(Self::extract_string), + http: extract_http_data(span, &self.expose_trace_id_config), + client_name: span.attributes.get(&CLIENT_NAME).and_then(extract_string), client_version: span .attributes .get(&CLIENT_VERSION) - .and_then(Self::extract_string), + .and_then(extract_string), operation_signature: span .attributes .get(&APOLLO_PRIVATE_OPERATION_SIGNATURE) - .and_then(Self::extract_string) + .and_then(extract_string) + .unwrap_or_default(), + operation_name: span + .attributes + .get(&OPERATION_NAME) + .and_then(extract_string) + .unwrap_or_default(), + variables_json: span + .attributes + .get(&APOLLO_PRIVATE_GRAPHQL_VARIABLES) + .and_then(extract_json) .unwrap_or_default(), }); child_nodes @@ -363,98 +344,181 @@ impl Exporter { self.extract_root_trace(span, child_nodes), )] } + DEFER_SPAN_NAME => { + vec![TreeData::QueryPlanNode(QueryPlanNode { + node: Some(crate::spaceport::trace::query_plan_node::Node::Defer( + Box::new(DeferNode { + primary: child_nodes.remove_first_defer_primary_node().map(Box::new), + deferred: child_nodes.remove_defer_deferred_nodes(), + }), + )), + })] + } + DEFER_PRIMARY_SPAN_NAME => { + vec![TreeData::DeferPrimary(DeferNodePrimary { + node: child_nodes.remove_first_query_plan_node().map(Box::new), + })] + } + DEFER_DEFERRED_SPAN_NAME => { + vec![TreeData::DeferDeferred(DeferredNode { + node: child_nodes.remove_first_query_plan_node(), + path: span + .attributes + .get(&PATH) + .map(extract_path) + .unwrap_or_default(), + // In theory we don't have to do the transformation here, but it is safer to do so. + depends: span + .attributes + .get(&DEPENDS) + .and_then(extract_json::>) + .unwrap_or_default() + .iter() + .map(|d| DeferredNodeDepends { + id: d.id.clone(), + defer_label: d.defer_label.clone().unwrap_or_default(), + }) + .collect(), + label: span + .attributes + .get(&LABEL) + .and_then(extract_string) + .unwrap_or_default(), + })] + } + + CONDITION_SPAN_NAME => { + vec![TreeData::QueryPlanNode(QueryPlanNode { + node: Some(crate::spaceport::trace::query_plan_node::Node::Condition( + Box::new(ConditionNode { + condition: span + .attributes + .get(&CONDITION) + .and_then(extract_string) + .unwrap_or_default(), + if_clause: child_nodes.remove_first_condition_if_node().map(Box::new), + else_clause: child_nodes + .remove_first_condition_else_node() + .map(Box::new), + }), + )), + })] + } + CONDITION_IF_SPAN_NAME => { + vec![TreeData::ConditionIf( + child_nodes.remove_first_query_plan_node(), + )] + } + CONDITION_ELSE_SPAN_NAME => { + vec![TreeData::ConditionElse( + child_nodes.remove_first_query_plan_node(), + )] + } _ => child_nodes, }) } +} - fn extract_string(v: &Value) -> Option { - if let Value::String(v) = v { - Some(v.to_string()) - } else { - None - } - } +fn extract_json(v: &Value) -> Option { + extract_string(v) + .map(|v| serde_json::from_str(&v)) + .transpose() + .unwrap_or(None) +} - fn extract_i64(v: &Value) -> Option { - if let Value::I64(v) = v { - Some(*v) - } else { - None - } +fn extract_string(v: &Value) -> Option { + if let Value::String(v) = v { + Some(v.to_string()) + } else { + None } +} - fn find_ftv1_trace( - &mut self, - span: &SpanData, - ) -> Result>, Error> { - span.attributes - .get(&APOLLO_PRIVATE_FTV1) - .map(|data| { - if let Value::String(data) = data { - Ok(Box::new(crate::spaceport::Trace::decode(Cursor::new( - base64::decode(data.to_string())?, - ))?)) +fn extract_path(v: &Value) -> Vec { + extract_string(v) + .map(|v| { + v.split('/').filter(|v|!v.is_empty() && *v != "@").map(|v| { + if let Ok(index) = v.parse::() { + ResponsePathElement { id: Some(crate::spaceport::trace::query_plan_node::response_path_element::Id::Index(index))} } else { - Err(Error::Ftv1SpanAttribute) + ResponsePathElement { id: Some(crate::spaceport::trace::query_plan_node::response_path_element::Id::FieldName(v.to_string())) } } - }) - .transpose() + }).collect() + }).unwrap_or_default() +} + +fn extract_i64(v: &Value) -> Option { + if let Value::I64(v) = v { + Some(*v) + } else { + None } +} - fn extract_http_data(&self, span: &SpanData) -> Http { - let method = match span - .attributes - .get(&HTTP_METHOD) - .map(|data| data.as_str()) - .unwrap_or_default() - .as_ref() - { - "OPTIONS" => crate::spaceport::trace::http::Method::Options, - "GET" => crate::spaceport::trace::http::Method::Get, - "HEAD" => crate::spaceport::trace::http::Method::Head, - "POST" => crate::spaceport::trace::http::Method::Post, - "PUT" => crate::spaceport::trace::http::Method::Put, - "DELETE" => crate::spaceport::trace::http::Method::Delete, - "TRACE" => crate::spaceport::trace::http::Method::Trace, - "CONNECT" => crate::spaceport::trace::http::Method::Connect, - "PATCH" => crate::spaceport::trace::http::Method::Patch, - _ => crate::spaceport::trace::http::Method::Unknown, - }; - let headers = span - .attributes - .get(&APOLLO_PRIVATE_HTTP_REQUEST_HEADERS) - .map(|data| data.as_str()) - .unwrap_or_default(); - let request_headers = serde_json::from_str::>>(&headers) - .unwrap_or_default() - .into_iter() - .map(|(header_name, value)| (header_name.to_lowercase(), Values { value })) - .collect(); - // For now, only trace_id - let response_headers = if self.expose_trace_id_config.enabled { - let mut res = HashMap::with_capacity(1); - res.insert( - self.expose_trace_id_config - .header_name - .as_ref() - .map(|h| h.to_string()) - .unwrap_or_else(|| DEFAULT_TRACE_ID_HEADER_NAME.to_string()), - Values { - value: vec![span.span_context.trace_id().to_string()], - }, - ); +fn extract_ftv1_trace(v: &Value) -> Option, Error>> { + if let Some(v) = extract_string(v) { + if let Ok(v) = base64::decode(v) { + if let Ok(t) = crate::spaceport::Trace::decode(Cursor::new(v)) { + return Some(Ok(Box::new(t))); + } + } - res - } else { - HashMap::new() - }; + return Some(Err(Error::TraceParsingFailed)); + } + None +} - Http { - method: method.into(), - request_headers, - response_headers, - status_code: 0, - } +fn extract_http_data(span: &SpanData, expose_trace_id_config: &ExposeTraceId) -> Http { + let method = match span + .attributes + .get(&HTTP_METHOD) + .map(|data| data.as_str()) + .unwrap_or_default() + .as_ref() + { + "OPTIONS" => crate::spaceport::trace::http::Method::Options, + "GET" => crate::spaceport::trace::http::Method::Get, + "HEAD" => crate::spaceport::trace::http::Method::Head, + "POST" => crate::spaceport::trace::http::Method::Post, + "PUT" => crate::spaceport::trace::http::Method::Put, + "DELETE" => crate::spaceport::trace::http::Method::Delete, + "TRACE" => crate::spaceport::trace::http::Method::Trace, + "CONNECT" => crate::spaceport::trace::http::Method::Connect, + "PATCH" => crate::spaceport::trace::http::Method::Patch, + _ => crate::spaceport::trace::http::Method::Unknown, + }; + let request_headers = span + .attributes + .get(&APOLLO_PRIVATE_HTTP_REQUEST_HEADERS) + .and_then(extract_json::>>) + .unwrap_or_default() + .into_iter() + .map(|(header_name, value)| (header_name.to_lowercase(), Values { value })) + .collect(); + // For now, only trace_id + let response_headers = if expose_trace_id_config.enabled { + let mut res = HashMap::with_capacity(1); + res.insert( + expose_trace_id_config + .header_name + .as_ref() + .map(|h| h.to_string()) + .unwrap_or_else(|| DEFAULT_TRACE_ID_HEADER_NAME.to_string()), + Values { + value: vec![span.span_context.trace_id().to_string()], + }, + ); + + res + } else { + HashMap::new() + }; + + Http { + method: method.into(), + request_headers, + response_headers, + status_code: 0, } } @@ -470,6 +534,17 @@ impl SpanExporter for Exporter { let mut traces: Vec<(String, crate::spaceport::Trace)> = Vec::new(); for span in batch { if span.name == REQUEST_SPAN_NAME { + // Write spans for testing + // You can obtain new span data by uncommenting the following code and executing a query. + // In general this isn't something we'll want to do often, we are just verifying that the exporter constructs a correct report. + // let mut c = self + // .spans_by_parent_id + // .iter() + // .flat_map(|(_, s)| s.iter()) + // .collect::>(); + // c.push(&span); + // std::fs::write("spandata.yaml", serde_yaml::to_string(&c).unwrap()).unwrap(); + match self.extract_trace(span) { Ok(mut trace) => { let mut operation_signature = Default::default(); @@ -479,17 +554,10 @@ impl SpanExporter for Exporter { } } Err(Error::MultipleErrors(errors)) => { - if let Some(Error::DoNotSample(reason)) = errors.first() { - tracing::debug!( - "sampling is disabled on this trace: {}, skipping", - reason - ); - } else { - tracing::error!( - "failed to construct trace: {}, skipping", - Error::MultipleErrors(errors) - ); - } + tracing::error!( + "failed to construct trace: {}, skipping", + Error::MultipleErrors(errors) + ); } Err(error) => { tracing::error!("failed to construct trace: {}, skipping", error); @@ -514,3 +582,365 @@ impl SpanExporter for Exporter { return ExportResult::Ok(()); } } + +trait ChildNodes { + fn remove_first_query_plan_node(&mut self) -> Option; + fn remove_query_plan_nodes(&mut self) -> Vec; + fn remove_first_defer_primary_node(&mut self) -> Option; + fn remove_defer_deferred_nodes(&mut self) -> Vec; + fn remove_first_condition_if_node(&mut self) -> Option; + fn remove_first_condition_else_node(&mut self) -> Option; +} + +impl ChildNodes for Vec { + fn remove_first_query_plan_node(&mut self) -> Option { + if let Some((idx, _)) = self + .iter() + .find_position(|child| matches!(child, TreeData::QueryPlanNode(_))) + { + if let TreeData::QueryPlanNode(node) = self.remove(idx) { + return Some(node); + } + } + None + } + + fn remove_query_plan_nodes(&mut self) -> Vec { + let mut extracted = Vec::new(); + let mut retained = Vec::new(); + for treedata in self.drain(0..self.len()) { + if let TreeData::QueryPlanNode(node) = treedata { + extracted.push(node); + } else { + retained.push(treedata) + } + } + self.append(&mut retained); + extracted + } + + fn remove_first_defer_primary_node(&mut self) -> Option { + if let Some((idx, _)) = self + .iter() + .find_position(|child| matches!(child, TreeData::DeferPrimary(_))) + { + if let TreeData::DeferPrimary(node) = self.remove(idx) { + return Some(node); + } + } + None + } + + fn remove_defer_deferred_nodes(&mut self) -> Vec { + let mut extracted = Vec::new(); + let mut retained = Vec::new(); + for treedata in self.drain(0..self.len()) { + if let TreeData::DeferDeferred(node) = treedata { + extracted.push(node); + } else { + retained.push(treedata) + } + } + self.append(&mut retained); + extracted + } + + fn remove_first_condition_if_node(&mut self) -> Option { + if let Some((idx, _)) = self + .iter() + .find_position(|child| matches!(child, TreeData::ConditionIf(_))) + { + if let TreeData::ConditionIf(node) = self.remove(idx) { + return node; + } + } + None + } + + fn remove_first_condition_else_node(&mut self) -> Option { + if let Some((idx, _)) = self + .iter() + .find_position(|child| matches!(child, TreeData::ConditionElse(_))) + { + if let TreeData::ConditionElse(node) = self.remove(idx) { + return node; + } + } + None + } +} + +#[buildstructor::buildstructor] +#[cfg(test)] +impl Exporter { + #[builder] + pub(crate) fn test_new(expose_trace_id_config: Option) -> Self { + Exporter { + expose_trace_id_config: expose_trace_id_config.unwrap_or_default(), + spans_by_parent_id: LruCache::unbounded(), + apollo_sender: Sender::InMemory(Default::default()), + field_execution_weight: 1.0, + } + } +} + +#[cfg(test)] +mod test { + use std::borrow::Cow; + + use http::header::HeaderName; + use opentelemetry::sdk::export::trace::SpanExporter; + use opentelemetry::Value; + use prost::Message; + use serde_json::json; + + use crate::plugins::telemetry::apollo::SingleReport; + use crate::plugins::telemetry::apollo_exporter::Sender; + use crate::plugins::telemetry::config::ExposeTraceId; + use crate::plugins::telemetry::tracing::apollo_telemetry::extract_ftv1_trace; + use crate::plugins::telemetry::tracing::apollo_telemetry::extract_i64; + use crate::plugins::telemetry::tracing::apollo_telemetry::extract_json; + use crate::plugins::telemetry::tracing::apollo_telemetry::extract_path; + use crate::plugins::telemetry::tracing::apollo_telemetry::extract_string; + use crate::plugins::telemetry::tracing::apollo_telemetry::ChildNodes; + use crate::plugins::telemetry::tracing::apollo_telemetry::Exporter; + use crate::plugins::telemetry::tracing::apollo_telemetry::TreeData; + use crate::spaceport; + use crate::spaceport::trace::query_plan_node::response_path_element::Id; + use crate::spaceport::trace::query_plan_node::DeferNodePrimary; + use crate::spaceport::trace::query_plan_node::DeferredNode; + use crate::spaceport::trace::query_plan_node::ResponsePathElement; + use crate::spaceport::trace::QueryPlanNode; + + async fn report(mut exporter: Exporter, spandata: &str) -> SingleReport { + let spandata = serde_yaml::from_str(spandata).expect("test spans must be parsable"); + + exporter + .export(spandata) + .await + .expect("span export must succeed"); + assert!(matches!(exporter.apollo_sender, Sender::InMemory(_))); + if let Sender::InMemory(storage) = exporter.apollo_sender { + return storage + .lock() + .expect("lock poisoned") + .pop() + .expect("must have a report"); + } + panic!("cannot happen"); + } + + macro_rules! assert_report { + ($report: expr)=> { + insta::with_settings!({sort_maps => true}, { + insta::assert_yaml_snapshot!($report, { + ".**.seconds" => "[seconds]", + ".**.nanos" => "[nanos]", + ".**.duration_ns" => "[duration_ns]", + ".**.child[].start_time" => "[start_time]", + ".**.child[].end_time" => "[end_time]", + ".**.trace_id.value[]" => "[trace_id]", + ".**.sent_time_offset" => "[sent_time_offset]" + }); + }); + } + } + + #[tokio::test] + async fn test_condition_if() { + // The following curl request was used to generate this span data + // curl --request POST \ + // --header 'content-type: application/json' \ + // --header 'accept: multipart/mixed; deferSpec=20220824, application/json' \ + // --url http://localhost:4000/ \ + // --data '{"query":"query($if: Boolean!) {\n topProducts {\n name\n ... @defer(if: $if) {\n reviews {\n author {\n name\n }\n }\n reviews {\n author {\n name\n }\n }\n }\n }\n}","variables":{"if":true}}' + let spandata = include_str!("testdata/condition_if_spandata.yaml"); + let exporter = Exporter::test_builder().build(); + let report = report(exporter, spandata).await; + assert_report!(report); + } + + #[tokio::test] + async fn test_condition_else() { + // The following curl request was used to generate this span data + // curl --request POST \ + // --header 'content-type: application/json' \ + // --header 'accept: multipart/mixed; deferSpec=20220824, application/json' \ + // --url http://localhost:4000/ \ + // --data '{"query":"query($if: Boolean!) {\n topProducts {\n name\n ... @defer(if: $if) {\n reviews {\n author {\n name\n }\n }\n reviews {\n author {\n name\n }\n }\n }\n }\n}","variables":{"if":false}}' + let spandata = include_str!("testdata/condition_else_spandata.yaml"); + let exporter = Exporter::test_builder().build(); + let report = report(exporter, spandata).await; + assert_report!(report); + } + + #[tokio::test] + async fn test_trace_id() { + let spandata = include_str!("testdata/condition_if_spandata.yaml"); + let exporter = Exporter::test_builder() + .expose_trace_id_config(ExposeTraceId { + enabled: true, + header_name: Some(HeaderName::from_static("trace_id")), + }) + .build(); + let report = report(exporter, spandata).await; + assert_report!(report); + } + + fn elements(tree_data: Vec) -> Vec<&'static str> { + let mut elements = Vec::new(); + for t in tree_data { + match t { + TreeData::Request(_) => elements.push("request"), + TreeData::Supergraph { .. } => elements.push("supergraph"), + TreeData::QueryPlanNode(_) => elements.push("query_plan_node"), + TreeData::DeferPrimary(_) => elements.push("defer_primary"), + TreeData::DeferDeferred(_) => elements.push("defer_deferred"), + TreeData::ConditionIf(_) => elements.push("condition_if"), + TreeData::ConditionElse(_) => elements.push("condition_else"), + TreeData::Trace(_) => elements.push("trace"), + } + } + elements + } + + #[test] + fn remove_first_query_plan_node() { + let mut vec = vec![ + TreeData::Trace(None), + TreeData::QueryPlanNode(QueryPlanNode { node: None }), + TreeData::QueryPlanNode(QueryPlanNode { node: None }), + ]; + + assert!(vec.remove_first_query_plan_node().is_some()); + assert_eq!(elements(vec), ["trace", "query_plan_node"]); + } + + #[test] + fn remove_query_plan_nodes() { + let mut vec = vec![ + TreeData::Trace(None), + TreeData::QueryPlanNode(QueryPlanNode { node: None }), + TreeData::QueryPlanNode(QueryPlanNode { node: None }), + ]; + + assert_eq!(vec.remove_query_plan_nodes().len(), 2); + assert_eq!(elements(vec), ["trace"]); + } + + #[test] + fn remove_first_defer_primary_node() { + let mut vec = vec![ + TreeData::Trace(None), + TreeData::DeferPrimary(DeferNodePrimary { node: None }), + TreeData::DeferDeferred(DeferredNode { + depends: vec![], + label: "".to_string(), + path: Default::default(), + node: None, + }), + ]; + + assert!(vec.remove_first_defer_primary_node().is_some()); + assert_eq!(elements(vec), ["trace", "defer_deferred"]); + } + + #[test] + fn remove_defer_deferred_nodes() { + let mut vec = vec![ + TreeData::Trace(None), + TreeData::DeferPrimary(DeferNodePrimary { node: None }), + TreeData::DeferDeferred(DeferredNode { + depends: vec![], + label: "".to_string(), + path: Default::default(), + node: None, + }), + TreeData::DeferDeferred(DeferredNode { + depends: vec![], + label: "".to_string(), + path: Default::default(), + node: None, + }), + ]; + + assert_eq!(vec.remove_defer_deferred_nodes().len(), 2); + assert_eq!(elements(vec), ["trace", "defer_primary"]); + } + + #[test] + fn test_remove_first_condition_if_node() { + let mut vec = vec![ + TreeData::Trace(None), + TreeData::ConditionIf(Some(QueryPlanNode { node: None })), + TreeData::ConditionElse(Some(QueryPlanNode { node: None })), + ]; + + assert!(vec.remove_first_condition_if_node().is_some()); + assert_eq!(elements(vec), ["trace", "condition_else"]); + } + + #[test] + fn test_remove_first_condition_else_node() { + let mut vec = vec![ + TreeData::Trace(None), + TreeData::ConditionIf(Some(QueryPlanNode { node: None })), + TreeData::ConditionElse(Some(QueryPlanNode { node: None })), + ]; + + assert!(vec.remove_first_condition_else_node().is_some()); + assert_eq!(elements(vec), ["trace", "condition_if"]); + } + + #[test] + fn test_extract_json() { + let val = json!({"hi": "there"}); + assert_eq!( + extract_json::(&Value::String(Cow::Owned(val.to_string()))), + Some(val) + ); + } + + #[test] + fn test_extract_string() { + assert_eq!( + extract_string(&Value::String(Cow::Owned("hi".to_string()))), + Some("hi".to_string()) + ); + } + + #[test] + fn test_extract_path() { + assert_eq!( + extract_path(&Value::String(Cow::Owned("/hi/3/there".to_string()))), + vec![ + ResponsePathElement { + id: Some(Id::FieldName("hi".to_string())), + }, + ResponsePathElement { + id: Some(Id::Index(3)), + }, + ResponsePathElement { + id: Some(Id::FieldName("there".to_string())), + } + ] + ); + } + + #[test] + fn test_extract_i64() { + assert_eq!(extract_i64(&Value::I64(35)), Some(35)); + } + + #[test] + fn test_extract_ftv1_trace() { + let trace = spaceport::Trace::default(); + let encoded = base64::encode(trace.encode_to_vec()); + assert_eq!( + *extract_ftv1_trace(&Value::String(Cow::Owned(encoded))) + .expect("there was a trace here") + .expect("the trace must be decoded"), + trace + ); + } +} diff --git a/apollo-router/src/plugins/telemetry/tracing/snapshots/apollo_router__plugins__telemetry__tracing__apollo_telemetry__test__condition_else.snap b/apollo-router/src/plugins/telemetry/tracing/snapshots/apollo_router__plugins__telemetry__tracing__apollo_telemetry__test__condition_else.snap new file mode 100644 index 0000000000..b7fc231720 --- /dev/null +++ b/apollo-router/src/plugins/telemetry/tracing/snapshots/apollo_router__plugins__telemetry__tracing__apollo_telemetry__test__condition_else.snap @@ -0,0 +1,593 @@ +--- +source: apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs +expression: report +--- +Traces: + traces: + - - "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}" + - 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: + if: "false" + operation_name: "" + client_name: "" + client_version: "" + http: + method: 4 + request_headers: + accept: + value: + - "" + content-length: + value: + - "" + content-type: + value: + - "" + host: + value: + - "" + user-agent: + value: + - "" + response_headers: {} + status_code: 0 + cache_policy: ~ + query_plan: + node: + Condition: + condition: if + if_clause: ~ + else_clause: + 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: "" + 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 + 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: "" + 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 + 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 + - 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: 2 + - 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: 3 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + 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 + 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 + diff --git a/apollo-router/src/plugins/telemetry/tracing/snapshots/apollo_router__plugins__telemetry__tracing__apollo_telemetry__test__condition_if.snap b/apollo-router/src/plugins/telemetry/tracing/snapshots/apollo_router__plugins__telemetry__tracing__apollo_telemetry__test__condition_if.snap new file mode 100644 index 0000000000..72ca9af214 --- /dev/null +++ b/apollo-router/src/plugins/telemetry/tracing/snapshots/apollo_router__plugins__telemetry__tracing__apollo_telemetry__test__condition_if.snap @@ -0,0 +1,606 @@ +--- +source: apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs +expression: report +--- +Traces: + traces: + - - "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}" + - 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: + if: "true" + operation_name: "" + client_name: "" + client_version: "" + http: + method: 4 + request_headers: + accept: + value: + - "" + content-length: + value: + - "" + content-type: + value: + - "" + host: + value: + - "" + user-agent: + value: + - "" + response_headers: {} + status_code: 0 + cache_policy: ~ + query_plan: + node: + Condition: + condition: if + if_clause: + node: + Defer: + primary: + node: + 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: name + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + 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: name + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + 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: name + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + id: + Index: 2 + id: + ResponseName: topProducts + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + 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 + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + deferred: + - depends: + - id: "0" + defer_label: "" + label: "" + path: + - id: + FieldName: topProducts + node: + node: + Sequence: + nodes: + - 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: "" + 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 + 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 + - 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: 2 + - 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: 3 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + 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 + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + else_clause: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + diff --git a/apollo-router/src/plugins/telemetry/tracing/snapshots/apollo_router__plugins__telemetry__tracing__apollo_telemetry__test__trace_id.snap b/apollo-router/src/plugins/telemetry/tracing/snapshots/apollo_router__plugins__telemetry__tracing__apollo_telemetry__test__trace_id.snap new file mode 100644 index 0000000000..706a60cea1 --- /dev/null +++ b/apollo-router/src/plugins/telemetry/tracing/snapshots/apollo_router__plugins__telemetry__tracing__apollo_telemetry__test__trace_id.snap @@ -0,0 +1,609 @@ +--- +source: apollo-router/src/plugins/telemetry/tracing/apollo_telemetry.rs +expression: report +--- +Traces: + traces: + - - "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}" + - 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: + if: "true" + operation_name: "" + client_name: "" + client_version: "" + http: + method: 4 + request_headers: + accept: + value: + - "" + content-length: + value: + - "" + content-type: + value: + - "" + host: + value: + - "" + user-agent: + value: + - "" + response_headers: + trace_id: + value: + - "[trace_id]" + status_code: 0 + cache_policy: ~ + query_plan: + node: + Condition: + condition: if + if_clause: + node: + Defer: + primary: + node: + 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: name + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + 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: name + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + 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: name + - original_field_name: "" + type: String! + parent_type: Product + cache_policy: ~ + start_time: "[start_time]" + end_time: "[end_time]" + error: [] + child: [] + id: + ResponseName: upc + id: + Index: 2 + id: + ResponseName: topProducts + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + 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 + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + deferred: + - depends: + - id: "0" + defer_label: "" + label: "" + path: + - id: + FieldName: topProducts + node: + node: + Sequence: + nodes: + - 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: "" + 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 + 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 + - 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: 2 + - 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: 3 + id: + ResponseName: _entities + id: ~ + is_incomplete: false + signature: "" + unexecuted_operation_body: "" + unexecuted_operation_name: "" + details: ~ + client_name: "" + client_version: "" + 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 + sent_time_offset: "[sent_time_offset]" + sent_time: + seconds: "[seconds]" + nanos: "[nanos]" + received_time: + seconds: "[seconds]" + nanos: "[nanos]" + else_clause: ~ + full_query_cache_hit: false + persisted_query_hit: false + persisted_query_register: false + registered_operation: false + forbidden_operation: false + field_execution_weight: 1 + diff --git a/apollo-router/src/plugins/telemetry/tracing/testdata/condition_else_spandata.yaml b/apollo-router/src/plugins/telemetry/tracing/testdata/condition_else_spandata.yaml new file mode 100644 index 0000000000..158ec9527b --- /dev/null +++ b/apollo-router/src/plugins/telemetry/tracing/testdata/condition_else_spandata.yaml @@ -0,0 +1,1252 @@ +--- +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 14287822546131581520 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 17691584597033290046 + span_kind: Internal + name: supergraph + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 867241222 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 996401974 + attributes: + map: + code.filepath: + String: apollo-router/src/plugins/telemetry/mod.rs + code.lineno: + I64: 673 + graphql.operation.name: + String: "" + apollo_private.http.request_headers: + String: "{\"accept\":[\"\"],\"content-length\":[\"\"],\"content-type\":[\"\"],\"host\":[\"\"],\"user-agent\":[\"\"]}" + client.version: + String: "" + graphql.document: + String: "query($if: Boolean!) {\n topProducts {\n name\n ... @defer(if: $if) {\n reviews {\n author {\n name\n }\n }\n reviews {\n author {\n name\n }\n }\n }\n }\n}" + apollo_private.graphql.variables: + String: "{\"if\":\"false\"}" + thread.name: + String: tokio-runtime-worker + busy_ns: + I64: 8691539 + code.namespace: + String: "apollo_router::plugins::telemetry" + client.name: + String: "" + idle_ns: + I64: 120357048 + thread.id: + I64: 16 + apollo_private.field_level_instrumentation_ratio: + F64: 1.0 + apollo_private.operation_signature: + String: "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}" + evict_list: + - idle_ns + - busy_ns + - apollo_private.operation_signature + - apollo_private.http.request_headers + - apollo_private.graphql.variables + - apollo_private.field_level_instrumentation_ratio + - client.version + - client.name + - graphql.operation.name + - graphql.document + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 15237674702119070751 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 14287822546131581520 + span_kind: Internal + name: query_planning + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 867688559 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 867984269 + attributes: + map: + thread.name: + String: tokio-runtime-worker + code.namespace: + String: "apollo_router::services::supergraph_service" + busy_ns: + I64: 202332 + thread.id: + I64: 16 + code.filepath: + String: apollo-router/src/services/supergraph_service.rs + idle_ns: + I64: 89188 + code.lineno: + I64: 247 + graphql.document: + String: "query($if: Boolean!) {\n topProducts {\n name\n ... @defer(if: $if) {\n reviews {\n author {\n name\n }\n }\n reviews {\n author {\n name\n }\n }\n }\n }\n}" + graphql.operation.name: + String: "" + evict_list: + - idle_ns + - busy_ns + - graphql.operation.name + - graphql.document + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 13865784024556574003 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 14287822546131581520 + span_kind: Internal + name: execution + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 868258608 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 995684698 + attributes: + map: + code.namespace: + String: "apollo_router::plugins::telemetry" + thread.name: + String: tokio-runtime-worker + thread.id: + I64: 16 + idle_ns: + I64: 119214086 + busy_ns: + I64: 8228208 + code.filepath: + String: apollo-router/src/plugins/telemetry/mod.rs + code.lineno: + I64: 283 + evict_list: + - idle_ns + - busy_ns + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 6782401025275156233 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 13865784024556574003 + span_kind: Internal + name: condition + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 868378386 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 995541872 + attributes: + map: + thread.name: + String: tokio-runtime-worker + code.lineno: + I64: 327 + thread.id: + I64: 16 + code.namespace: + String: "apollo_router::query_planner::execution" + busy_ns: + I64: 7912453 + code.filepath: + String: apollo-router/src/query_planner/execution.rs + graphql.condition: + String: if + idle_ns: + I64: 119255502 + evict_list: + - idle_ns + - busy_ns + - graphql.condition + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 8824695332656836540 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 6782401025275156233 + span_kind: Internal + name: condition_else + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 868436285 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 995438855 + attributes: + map: + thread.name: + String: tokio-runtime-worker + code.lineno: + I64: 320 + code.namespace: + String: "apollo_router::query_planner::execution" + thread.id: + I64: 16 + code.filepath: + String: apollo-router/src/query_planner/execution.rs + idle_ns: + I64: 119291958 + busy_ns: + I64: 7712497 + evict_list: + - idle_ns + - busy_ns + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 16743763821444799861 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 8824695332656836540 + span_kind: Internal + name: sequence + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 868481682 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 995362238 + attributes: + map: + idle_ns: + I64: 119470686 + code.filepath: + String: apollo-router/src/query_planner/execution.rs + code.lineno: + I64: 133 + thread.name: + String: tokio-runtime-worker + busy_ns: + I64: 7408892 + code.namespace: + String: "apollo_router::query_planner::execution" + thread.id: + I64: 16 + evict_list: + - idle_ns + - busy_ns + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 17407667985756513925 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 16743763821444799861 + span_kind: Internal + name: fetch + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 868543283 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 917023578 + attributes: + map: + busy_ns: + I64: 1986511 + thread.id: + I64: 16 + apollo_private.sent_time_offset: + I64: 1459136 + idle_ns: + I64: 46482889 + code.namespace: + String: "apollo_router::query_planner::execution" + code.lineno: + I64: 188 + apollo.subgraph.name: + String: products + thread.name: + String: tokio-runtime-worker + code.filepath: + String: apollo-router/src/query_planner/execution.rs + evict_list: + - idle_ns + - busy_ns + - apollo_private.sent_time_offset + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 7936167443054682587 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 16743763821444799861 + span_kind: Internal + name: flatten + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 917215783 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 955428350 + attributes: + map: + code.filepath: + String: apollo-router/src/query_planner/execution.rs + code.lineno: + I64: 176 + code.namespace: + String: "apollo_router::query_planner::execution" + graphql.path: + String: /topProducts/@ + idle_ns: + I64: 35904853 + busy_ns: + I64: 2314489 + thread.name: + String: tokio-runtime-worker + thread.id: + I64: 14 + evict_list: + - idle_ns + - busy_ns + - graphql.path + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 16253144712595734830 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 16743763821444799861 + span_kind: Internal + name: flatten + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 955665393 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 995190497 + attributes: + map: + code.lineno: + I64: 176 + code.namespace: + String: "apollo_router::query_planner::execution" + thread.id: + I64: 16 + busy_ns: + I64: 2347943 + idle_ns: + I64: 37184285 + code.filepath: + String: apollo-router/src/query_planner/execution.rs + thread.name: + String: tokio-runtime-worker + graphql.path: + String: /topProducts/@/reviews/@/author + evict_list: + - idle_ns + - busy_ns + - graphql.path + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 15278772753518055685 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 16253144712595734830 + span_kind: Internal + name: fetch + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 955768549 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 995068484 + attributes: + map: + apollo_private.sent_time_offset: + I64: 88681888 + code.filepath: + String: apollo-router/src/query_planner/execution.rs + code.namespace: + String: "apollo_router::query_planner::execution" + idle_ns: + I64: 37140006 + busy_ns: + I64: 2141909 + code.lineno: + I64: 188 + thread.id: + I64: 16 + thread.name: + String: tokio-runtime-worker + apollo.subgraph.name: + String: accounts + evict_list: + - idle_ns + - busy_ns + - apollo_private.sent_time_offset + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 11170049527526553842 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 15278772753518055685 + span_kind: Internal + name: subgraph + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 956111054 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 994769700 + attributes: + map: + busy_ns: + I64: 1390132 + thread.name: + String: tokio-runtime-worker + code.filepath: + String: apollo-router/src/plugins/telemetry/mod.rs + graphql.operation.name: + String: "" + code.namespace: + String: "apollo_router::plugins::telemetry" + graphql.document: + String: "query($representations:[_Any!]!){_entities(representations:$representations){...on User{name}}}" + apollo.subgraph.name: + String: accounts + apollo_private.ftv1: + String: GgwIw7WnnAYQgLGs0gMiDAjDtaecBhCAsazSA1isvR5ysQFirgEKCV9lbnRpdGllcxoKW19FbnRpdHldIUDn0BFI35cXYiAQAGIcCgRuYW1lGgZTdHJpbmdA8+4YSKOvGWoEVXNlcmIgEAFiHAoEbmFtZRoGU3RyaW5nQKuIGkiFsRpqBFVzZXJiIBACYhwKBG5hbWUaBlN0cmluZ0Dz3hpIofYaagRVc2VyYiAQA2IcCgRuYW1lGgZTdHJpbmdAxasbSJvDG2oEVXNlcmoFUXVlcnn5AQAAAAAAAPA/ + idle_ns: + I64: 37270820 + thread.id: + I64: 16 + code.lineno: + I64: 313 + evict_list: + - idle_ns + - busy_ns + - apollo_private.ftv1 + - graphql.operation.name + - graphql.document + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 12193731640433132388 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 11170049527526553842 + span_kind: Client + name: subgraph_request + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 956430440 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 993872582 + attributes: + map: + thread.id: + I64: 16 + code.filepath: + String: apollo-router/src/services/subgraph_service.rs + code.namespace: + String: "apollo_router::services::subgraph_service" + code.lineno: + I64: 173 + thread.name: + String: tokio-runtime-worker + net.peer.port: + String: "80" + net.transport: + String: ip_tcp + idle_ns: + I64: 37174926 + net.peer.name: + String: accounts.demo.starstuff.dev + http.route: + String: /graphql + apollo.subgraph.name: + String: accounts + busy_ns: + I64: 251431 + evict_list: + - idle_ns + - busy_ns + - apollo.subgraph.name + - net.transport + - http.route + - net.peer.port + - net.peer.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 17716600377366594972 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 7936167443054682587 + span_kind: Internal + name: fetch + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 917323270 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 955316673 + attributes: + map: + apollo.subgraph.name: + String: reviews + code.filepath: + String: apollo-router/src/query_planner/execution.rs + thread.name: + String: tokio-runtime-worker + code.namespace: + String: "apollo_router::query_planner::execution" + thread.id: + I64: 14 + busy_ns: + I64: 2122145 + idle_ns: + I64: 35855963 + apollo_private.sent_time_offset: + I64: 50235421 + code.lineno: + I64: 188 + evict_list: + - idle_ns + - busy_ns + - apollo_private.sent_time_offset + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 12581790234036960487 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 17716600377366594972 + span_kind: Internal + name: subgraph + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 917638675 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 955031718 + attributes: + map: + code.namespace: + String: "apollo_router::plugins::telemetry" + graphql.operation.name: + String: "" + thread.name: + String: tokio-runtime-worker + busy_ns: + I64: 1432596 + code.filepath: + String: apollo-router/src/plugins/telemetry/mod.rs + code.lineno: + I64: 313 + apollo.subgraph.name: + String: reviews + thread.id: + I64: 14 + graphql.document: + String: "query($representations:[_Any!]!){_entities(representations:$representations){...on Product{reviews{author{__typename id}}}}}" + idle_ns: + I64: 35964358 + apollo_private.ftv1: + String: GgwIw7WnnAYQgIadwAMiDAjDtaecBhDAgeC/A1iptVRynQNimgMKCV9lbnRpdGllcxoKW19FbnRpdHldIUCGqxRI7OwbYqMBEABingEKB3Jldmlld3MaCFtSZXZpZXddQOzKHki+hzBiOxAAYjcKBmF1dGhvchoEVXNlckDSmjJIxe1GYhcKAmlkGgNJRCFA6dZISJHFSWoEVXNlcmoGUmV2aWV3YjsQAWI3CgZhdXRob3IaBFVzZXJAlcs3SNH5SWIXCgJpZBoDSUQhQO/YSkidoktqBFVzZXJqBlJldmlld2oHUHJvZHVjdGJlEAFiYQoHcmV2aWV3cxoIW1Jldmlld11AmJgkSLmVO2I7EABiNwoGYXV0aG9yGgRVc2VyQMu0PEjrxEtiFwoCaWQaA0lEIUDRoExIieBMagRVc2VyagZSZXZpZXdqB1Byb2R1Y3RiZRACYmEKB3Jldmlld3MaCFtSZXZpZXddQJSRKUiz6j9iOxAAYjcKBmF1dGhvchoEVXNlckC9j0FI/YFNYhcKAmlkGgNJRCFAg/1NSM+oTmoEVXNlcmoGUmV2aWV3agdQcm9kdWN0agVRdWVyefkBAAAAAAAA8D8= + evict_list: + - idle_ns + - busy_ns + - apollo_private.ftv1 + - graphql.operation.name + - graphql.document + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 13059514760148115210 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 12581790234036960487 + span_kind: Client + name: subgraph_request + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 917936271 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 954080612 + attributes: + map: + thread.id: + I64: 14 + net.transport: + String: ip_tcp + http.route: + String: /graphql + code.filepath: + String: apollo-router/src/services/subgraph_service.rs + thread.name: + String: tokio-runtime-worker + code.lineno: + I64: 173 + busy_ns: + I64: 238580 + net.peer.port: + String: "80" + idle_ns: + I64: 35889487 + net.peer.name: + String: reviews.demo.starstuff.dev + apollo.subgraph.name: + String: reviews + code.namespace: + String: "apollo_router::services::subgraph_service" + evict_list: + - idle_ns + - busy_ns + - apollo.subgraph.name + - net.transport + - http.route + - net.peer.port + - net.peer.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 12520246751970884479 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 17407667985756513925 + span_kind: Internal + name: subgraph + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 868753996 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 916852605 + attributes: + map: + code.namespace: + String: "apollo_router::plugins::telemetry" + code.filepath: + String: apollo-router/src/plugins/telemetry/mod.rs + apollo.subgraph.name: + String: products + graphql.operation.name: + String: "" + graphql.document: + String: "{topProducts{__typename upc name}}" + idle_ns: + I64: 46604902 + apollo_private.ftv1: + String: GgwIw7WnnAYQwM3WrAMiDAjDtaecBhCAyZmsA1iQ8DJy/AFi+QEKC3RvcFByb2R1Y3RzGglbUHJvZHVjdF1AufwXSJb9ImJEEABiHwoDdXBjGgdTdHJpbmchQOHGJkjU7SdqB1Byb2R1Y3RiHwoEbmFtZRoGU3RyaW5nQNfIKEj3gSlqB1Byb2R1Y3RiRBABYh8KA3VwYxoHU3RyaW5nIUDOzCpInIEragdQcm9kdWN0Yh8KBG5hbWUaBlN0cmluZ0CGyitI6/MragdQcm9kdWN0YkQQAmIfCgN1cGMaB1N0cmluZyFAg5AtSIS9LWoHUHJvZHVjdGIfCgRuYW1lGgZTdHJpbmdAluMtSLqgLmoHUHJvZHVjdGoFUXVlcnn5AQAAAAAAAPA/ + busy_ns: + I64: 1496082 + code.lineno: + I64: 313 + thread.id: + I64: 16 + thread.name: + String: tokio-runtime-worker + evict_list: + - idle_ns + - busy_ns + - apollo_private.ftv1 + - graphql.operation.name + - graphql.document + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 3398738514204614748 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 12520246751970884479 + span_kind: Client + name: subgraph_request + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 869023655 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 915894445 + attributes: + map: + net.peer.name: + String: products.demo.starstuff.dev + code.namespace: + String: "apollo_router::services::subgraph_service" + idle_ns: + I64: 46547911 + http.route: + String: /graphql + net.peer.port: + String: "80" + net.transport: + String: ip_tcp + thread.id: + I64: 16 + busy_ns: + I64: 304371 + apollo.subgraph.name: + String: products + code.filepath: + String: apollo-router/src/services/subgraph_service.rs + code.lineno: + I64: 173 + thread.name: + String: tokio-runtime-worker + evict_list: + - idle_ns + - busy_ns + - apollo.subgraph.name + - net.transport + - http.route + - net.peer.port + - net.peer.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 122960190946202642409915189222685399094 + span_id: 17691584597033290046 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 0 + span_kind: Server + name: request + start_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 866508162 + end_time: + secs_since_epoch: 1669978819 + nanos_since_epoch: 996777793 + attributes: + map: + trace_id: + String: 5c8145789355263a300c728c5e71d836 + http.flavor: + String: HTTP/1.1 + http.method: + String: POST + code.namespace: + String: "apollo_router::axum_factory::utils" + code.filepath: + String: apollo-router/src/axum_factory/utils.rs + apollo_private.duration_ns: + I64: 130300920 + http.route: + String: / + code.lineno: + I64: 259 + busy_ns: + I64: 11197815 + thread.id: + I64: 16 + idle_ns: + I64: 119064623 + thread.name: + String: tokio-runtime-worker + evict_list: + - idle_ns + - busy_ns + - apollo_private.duration_ns + - trace_id + - http.flavor + - http.route + - http.method + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Ok + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 diff --git a/apollo-router/src/plugins/telemetry/tracing/testdata/condition_if_spandata.yaml b/apollo-router/src/plugins/telemetry/tracing/testdata/condition_if_spandata.yaml new file mode 100644 index 0000000000..a9ced9409c --- /dev/null +++ b/apollo-router/src/plugins/telemetry/tracing/testdata/condition_if_spandata.yaml @@ -0,0 +1,1441 @@ +--- +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 2226108203856432052 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 6681943477281517192 + span_kind: Internal + name: supergraph + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 694878120 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 831374780 + attributes: + map: + graphql.document: + String: "query($if: Boolean!) {\n topProducts {\n name\n ... @defer(if: $if) {\n reviews {\n author {\n name\n }\n }\n reviews {\n author {\n name\n }\n }\n }\n }\n}" + client.version: + String: "" + graphql.operation.name: + String: "" + apollo_private.http.request_headers: + String: "{\"accept\":[\"\"],\"content-length\":[\"\"],\"content-type\":[\"\"],\"host\":[\"\"],\"user-agent\":[\"\"]}" + apollo_private.field_level_instrumentation_ratio: + F64: 1.0 + busy_ns: + I64: 3579254 + code.filepath: + String: apollo-router/src/plugins/telemetry/mod.rs + apollo_private.operation_signature: + String: "# -\nquery($if:Boolean!){topProducts{name...@defer(if:$if){reviews{author{name}}reviews{author{name}}}}}" + apollo_private.graphql.variables: + String: "{\"if\":\"true\"}" + idle_ns: + I64: 132902529 + code.lineno: + I64: 673 + client.name: + String: "" + thread.name: + String: tokio-runtime-worker + thread.id: + I64: 15 + code.namespace: + String: "apollo_router::plugins::telemetry" + evict_list: + - idle_ns + - busy_ns + - apollo_private.operation_signature + - apollo_private.http.request_headers + - apollo_private.graphql.variables + - apollo_private.field_level_instrumentation_ratio + - client.version + - client.name + - graphql.operation.name + - graphql.document + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 7005602647906255377 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 2226108203856432052 + span_kind: Internal + name: query_planning + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 695299406 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 695547275 + attributes: + map: + thread.name: + String: tokio-runtime-worker + code.filepath: + String: apollo-router/src/services/supergraph_service.rs + code.lineno: + I64: 247 + graphql.operation.name: + String: "" + thread.id: + I64: 15 + graphql.document: + String: "query($if: Boolean!) {\n topProducts {\n name\n ... @defer(if: $if) {\n reviews {\n author {\n name\n }\n }\n reviews {\n author {\n name\n }\n }\n }\n }\n}" + busy_ns: + I64: 194440 + idle_ns: + I64: 70121 + code.namespace: + String: "apollo_router::services::supergraph_service" + evict_list: + - idle_ns + - busy_ns + - graphql.operation.name + - graphql.document + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 5496672787700345629 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 2226108203856432052 + span_kind: Internal + name: execution + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 695807715 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 830738870 + attributes: + map: + code.filepath: + String: apollo-router/src/plugins/telemetry/mod.rs + code.lineno: + I64: 283 + busy_ns: + I64: 2888938 + code.namespace: + String: "apollo_router::plugins::telemetry" + thread.id: + I64: 15 + thread.name: + String: tokio-runtime-worker + idle_ns: + I64: 45262821 + evict_list: + - idle_ns + - busy_ns + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 8052379820523592996 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 5496672787700345629 + span_kind: Internal + name: condition + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 695918484 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 830671333 + attributes: + map: + code.namespace: + String: "apollo_router::query_planner::execution" + idle_ns: + I64: 45284960 + code.lineno: + I64: 327 + thread.name: + String: tokio-runtime-worker + busy_ns: + I64: 2690658 + thread.id: + I64: 15 + code.filepath: + String: apollo-router/src/query_planner/execution.rs + graphql.condition: + String: if + evict_list: + - idle_ns + - busy_ns + - graphql.condition + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 14511206469911177014 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 8052379820523592996 + span_kind: Internal + name: condition_if + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 695977151 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 830608824 + attributes: + map: + code.lineno: + I64: 306 + thread.name: + String: tokio-runtime-worker + busy_ns: + I64: 2606848 + code.namespace: + String: "apollo_router::query_planner::execution" + thread.id: + I64: 15 + idle_ns: + I64: 45301861 + code.filepath: + String: apollo-router/src/query_planner/execution.rs + evict_list: + - idle_ns + - busy_ns + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 12847835672039219100 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 14511206469911177014 + span_kind: Internal + name: defer + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 696022339 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 830518170 + attributes: + map: + thread.name: + String: tokio-runtime-worker + idle_ns: + I64: 126457525 + busy_ns: + I64: 8029995 + code.filepath: + String: apollo-router/src/query_planner/execution.rs + code.lineno: + I64: 271 + thread.id: + I64: 15 + code.namespace: + String: "apollo_router::query_planner::execution" + evict_list: + - idle_ns + - busy_ns + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 4412163015592220412 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 12847835672039219100 + span_kind: Internal + name: defer_primary + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 696362399 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 743760914 + attributes: + map: + code.namespace: + String: "apollo_router::query_planner::execution" + code.lineno: + I64: 259 + thread.id: + I64: 15 + thread.name: + String: tokio-runtime-worker + code.filepath: + String: apollo-router/src/query_planner/execution.rs + idle_ns: + I64: 45358226 + busy_ns: + I64: 2046016 + evict_list: + - idle_ns + - busy_ns + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 1343706171599318485 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 12847835672039219100 + span_kind: Internal + name: defer_deferred + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 743955493 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 830061683 + attributes: + map: + graphql.depends: + String: "[{\"id\":\"0\",\"deferLabel\":null}]" + code.filepath: + String: apollo-router/src/query_planner/execution.rs + idle_ns: + I64: 79860304 + thread.name: + String: tokio-runtime-worker + graphql.path: + String: /topProducts/@ + code.lineno: + I64: 429 + code.namespace: + String: "apollo_router::query_planner::execution" + thread.id: + I64: 14 + busy_ns: + I64: 6254826 + evict_list: + - idle_ns + - busy_ns + - graphql.path + - graphql.depends + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 1615094331109834215 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 1343706171599318485 + span_kind: Internal + name: sequence + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 744057462 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 829959505 + attributes: + map: + code.filepath: + String: apollo-router/src/query_planner/execution.rs + code.lineno: + I64: 133 + thread.id: + I64: 14 + busy_ns: + I64: 5920423 + idle_ns: + I64: 79979594 + thread.name: + String: tokio-runtime-worker + code.namespace: + String: "apollo_router::query_planner::execution" + evict_list: + - idle_ns + - busy_ns + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 9487579781210749637 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 1615094331109834215 + span_kind: Internal + name: flatten + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 744129818 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 785840064 + attributes: + map: + idle_ns: + I64: 39187070 + code.namespace: + String: "apollo_router::query_planner::execution" + thread.name: + String: tokio-runtime-worker + code.filepath: + String: apollo-router/src/query_planner/execution.rs + code.lineno: + I64: 176 + thread.id: + I64: 14 + busy_ns: + I64: 2518567 + graphql.path: + String: /topProducts/@ + evict_list: + - idle_ns + - busy_ns + - graphql.path + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 4988545802786443624 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 1615094331109834215 + span_kind: Internal + name: flatten + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 786138149 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 829728538 + attributes: + map: + thread.name: + String: tokio-runtime-worker + idle_ns: + I64: 40783864 + graphql.path: + String: /topProducts/@/reviews/@/author + busy_ns: + I64: 2806594 + code.namespace: + String: "apollo_router::query_planner::execution" + code.lineno: + I64: 176 + code.filepath: + String: apollo-router/src/query_planner/execution.rs + thread.id: + I64: 10 + evict_list: + - idle_ns + - busy_ns + - graphql.path + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 4477074139770004131 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 4988545802786443624 + span_kind: Internal + name: fetch + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 786225452 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 829575654 + attributes: + map: + apollo_private.sent_time_offset: + I64: 91499517 + thread.id: + I64: 10 + code.namespace: + String: "apollo_router::query_planner::execution" + code.filepath: + String: apollo-router/src/query_planner/execution.rs + thread.name: + String: tokio-runtime-worker + code.lineno: + I64: 188 + apollo.subgraph.name: + String: accounts + busy_ns: + I64: 2573183 + idle_ns: + I64: 40767661 + evict_list: + - idle_ns + - busy_ns + - apollo_private.sent_time_offset + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 4307400006762176495 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 4477074139770004131 + span_kind: Internal + name: subgraph + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 786630674 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 829172108 + attributes: + map: + code.filepath: + String: apollo-router/src/plugins/telemetry/mod.rs + code.lineno: + I64: 313 + thread.id: + I64: 10 + graphql.document: + String: "query($representations:[_Any!]!){_entities(representations:$representations){...on User{name}}}" + busy_ns: + I64: 1669429 + thread.name: + String: tokio-runtime-worker + idle_ns: + I64: 40867534 + code.namespace: + String: "apollo_router::plugins::telemetry" + apollo_private.ftv1: + String: GgwI+LWnnAYQwMHbggMiDAj4taecBhCAvZ6CA1j2sDRysQFirgEKCV9lbnRpdGllcxoKW19FbnRpdHldIUD0/xtIsqwlYiAQAGIcCgRuYW1lGgZTdHJpbmdA5JEpSOaUKmoEVXNlcmIgEAFiHAoEbmFtZRoGU3RyaW5nQITYK0iQlSxqBFVzZXJiIBACYhwKBG5hbWUaBlN0cmluZ0Ckgy1IiLYtagRVc2VyYiAQA2IcCgRuYW1lGgZTdHJpbmdAlrUuSIiDL2oEVXNlcmoFUXVlcnn5AQAAAAAAAPA/ + graphql.operation.name: + String: "" + apollo.subgraph.name: + String: accounts + evict_list: + - idle_ns + - busy_ns + - apollo_private.ftv1 + - graphql.operation.name + - graphql.document + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 15682297860951097268 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 4307400006762176495 + span_kind: Client + name: subgraph_request + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 786922194 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 827988149 + attributes: + map: + code.namespace: + String: "apollo_router::services::subgraph_service" + net.peer.port: + String: "80" + apollo.subgraph.name: + String: accounts + code.filepath: + String: apollo-router/src/services/subgraph_service.rs + thread.name: + String: tokio-runtime-worker + http.route: + String: /graphql + idle_ns: + I64: 40798740 + code.lineno: + I64: 173 + net.peer.name: + String: accounts.demo.starstuff.dev + net.transport: + String: ip_tcp + thread.id: + I64: 10 + busy_ns: + I64: 244936 + evict_list: + - idle_ns + - busy_ns + - apollo.subgraph.name + - net.transport + - http.route + - net.peer.port + - net.peer.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 374273098096638287 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 9487579781210749637 + span_kind: Internal + name: fetch + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 744222848 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 785694374 + attributes: + map: + thread.id: + I64: 14 + apollo.subgraph.name: + String: reviews + apollo_private.sent_time_offset: + I64: 49483643 + code.filepath: + String: apollo-router/src/query_planner/execution.rs + idle_ns: + I64: 39184766 + code.namespace: + String: "apollo_router::query_planner::execution" + code.lineno: + I64: 188 + thread.name: + String: tokio-runtime-worker + busy_ns: + I64: 2283967 + evict_list: + - idle_ns + - busy_ns + - apollo_private.sent_time_offset + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 12633132268468348696 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 374273098096638287 + span_kind: Internal + name: subgraph + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 744492507 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 785324771 + attributes: + map: + code.filepath: + String: apollo-router/src/plugins/telemetry/mod.rs + apollo_private.ftv1: + String: GgwI+LWnnAYQgImV7wIiDAj4taecBhDA+93tAljn6poBcqgDYqUDCglfZW50aXRpZXMaCltfRW50aXR5XSFAqZQjSIKrL2KoARAAYqMBCgdyZXZpZXdzGghbUmV2aWV3XUC3/jNIzL9UYj0QAGI5CgZhdXRob3IaBFVzZXJApP1XSLPbfmIZCgJpZBoDSUQhQOflggFImIKEAWoEVXNlcmoGUmV2aWV3Yj4QAWI6CgZhdXRob3IaBFVzZXJA+eFgSNTHhAFiGQoCaWQaA0lEIUDyuYYBSNKmhwFqBFVzZXJqBlJldmlld2oHUHJvZHVjdGJoEAFiZAoHcmV2aWV3cxoIW1Jldmlld11A/IRCSIT0Z2I+EABiOgoGYXV0aG9yGgRVc2VyQJmBakjV0ocBYhkKAmlkGgNJRCFAp/eIAUiLsYkBagRVc2VyagZSZXZpZXdqB1Byb2R1Y3RiaBACYmQKB3Jldmlld3MaCFtSZXZpZXddQN6gSkjqnnJiPhAAYjoKBmF1dGhvchoEVXNlckDFsnVIt9WJAWIZCgJpZBoDSUQhQKvligFIj5yLAWoEVXNlcmoGUmV2aWV3agdQcm9kdWN0agVRdWVyefkBAAAAAAAA8D8= + thread.id: + I64: 14 + thread.name: + String: tokio-runtime-worker + apollo.subgraph.name: + String: reviews + code.lineno: + I64: 313 + graphql.operation.name: + String: "" + busy_ns: + I64: 1537429 + code.namespace: + String: "apollo_router::plugins::telemetry" + graphql.document: + String: "query($representations:[_Any!]!){_entities(representations:$representations){...on Product{reviews{author{__typename id}}}}}" + idle_ns: + I64: 39296791 + evict_list: + - idle_ns + - busy_ns + - apollo_private.ftv1 + - graphql.operation.name + - graphql.document + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 11564887256002176974 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 12633132268468348696 + span_kind: Client + name: subgraph_request + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 744791989 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 784339792 + attributes: + map: + apollo.subgraph.name: + String: reviews + idle_ns: + I64: 39220524 + code.lineno: + I64: 173 + http.route: + String: /graphql + thread.name: + String: tokio-runtime-worker + net.peer.name: + String: reviews.demo.starstuff.dev + code.namespace: + String: "apollo_router::services::subgraph_service" + code.filepath: + String: apollo-router/src/services/subgraph_service.rs + net.peer.port: + String: "80" + thread.id: + I64: 14 + net.transport: + String: ip_tcp + busy_ns: + I64: 303323 + evict_list: + - idle_ns + - busy_ns + - apollo.subgraph.name + - net.transport + - http.route + - net.peer.port + - net.peer.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 13334624373206909001 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 4412163015592220412 + span_kind: Internal + name: fetch + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 696431123 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 743652030 + attributes: + map: + code.namespace: + String: "apollo_router::query_planner::execution" + thread.name: + String: tokio-runtime-worker + code.lineno: + I64: 188 + thread.id: + I64: 15 + busy_ns: + I64: 1848154 + apollo.subgraph.name: + String: products + idle_ns: + I64: 45372963 + code.filepath: + String: apollo-router/src/query_planner/execution.rs + apollo_private.sent_time_offset: + I64: 1705118 + evict_list: + - idle_ns + - busy_ns + - apollo_private.sent_time_offset + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 357853883512773358 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 13334624373206909001 + span_kind: Internal + name: subgraph + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 696595810 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 743458778 + attributes: + map: + apollo_private.ftv1: + String: GgwI+LWnnAYQgMyR2wIiDAj4taecBhDAvtrZAli8irwBcokCYoYCCgt0b3BQcm9kdWN0cxoJW1Byb2R1Y3RdQJWWE0jj/KQBYkgQAGIhCgRuYW1lGgZTdHJpbmdAuqerAUiEsqwBagdQcm9kdWN0YiEKA3VwYxoHU3RyaW5nIUDtkq4BSIXgrgFqB1Byb2R1Y3RiSBABYiEKBG5hbWUaBlN0cmluZ0CKoLABSMjOsAFqB1Byb2R1Y3RiIQoDdXBjGgdTdHJpbmchQKSDsQFIjfyzAWoHUHJvZHVjdGJIEAJiIQoEbmFtZRoGU3RyaW5nQPGPtQFIsOO1AWoHUHJvZHVjdGIhCgN1cGMaB1N0cmluZyFA7pm2AUjwvLYBagdQcm9kdWN0agVRdWVyefkBAAAAAAAA8D8= + busy_ns: + I64: 1359192 + code.filepath: + String: apollo-router/src/plugins/telemetry/mod.rs + idle_ns: + I64: 45508525 + code.lineno: + I64: 313 + apollo.subgraph.name: + String: products + code.namespace: + String: "apollo_router::plugins::telemetry" + thread.id: + I64: 15 + thread.name: + String: tokio-runtime-worker + graphql.document: + String: "{topProducts{__typename name upc}}" + graphql.operation.name: + String: "" + evict_list: + - idle_ns + - busy_ns + - apollo_private.ftv1 + - graphql.operation.name + - graphql.document + - apollo.subgraph.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 18275235823533906477 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 357853883512773358 + span_kind: Client + name: subgraph_request + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 696871895 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 742639533 + attributes: + map: + net.peer.name: + String: products.demo.starstuff.dev + http.route: + String: /graphql + code.lineno: + I64: 173 + busy_ns: + I64: 304929 + thread.id: + I64: 15 + thread.name: + String: tokio-runtime-worker + apollo.subgraph.name: + String: products + code.namespace: + String: "apollo_router::services::subgraph_service" + net.peer.port: + String: "80" + code.filepath: + String: apollo-router/src/services/subgraph_service.rs + idle_ns: + I64: 45448321 + net.transport: + String: ip_tcp + evict_list: + - idle_ns + - busy_ns + - apollo.subgraph.name + - net.transport + - http.route + - net.peer.port + - net.peer.name + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Unset + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 +- span_context: + trace_id: 48179106241482103848812575548686436429 + span_id: 6681943477281517192 + trace_flags: 1 + is_remote: false + trace_state: ~ + parent_span_id: 0 + span_kind: Server + name: request + start_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 694077802 + end_time: + secs_since_epoch: 1669978872 + nanos_since_epoch: 831560350 + attributes: + map: + idle_ns: + I64: 131480409 + apollo_private.duration_ns: + I64: 50655519 + code.namespace: + String: "apollo_router::axum_factory::utils" + code.filepath: + String: apollo-router/src/axum_factory/utils.rs + thread.name: + String: tokio-runtime-worker + http.method: + String: POST + http.flavor: + String: HTTP/1.1 + busy_ns: + I64: 5802181 + trace_id: + String: 243ef555cc5e90c7f03a859b1c3f884d + thread.id: + I64: 15 + http.route: + String: / + code.lineno: + I64: 259 + evict_list: + - idle_ns + - busy_ns + - apollo_private.duration_ns + - trace_id + - http.flavor + - http.route + - http.method + - thread.name + - thread.id + - code.lineno + - code.namespace + - code.filepath + max_len: 128 + dropped_count: 0 + events: + queue: ~ + max_len: 128 + dropped_count: 0 + links: + queue: ~ + max_len: 128 + dropped_count: 0 + status_code: Ok + status_message: "" + resource: + attrs: + foo: + String: bar + process.executable.name: + String: router + service.name: + String: router + service.version: + String: 1.4.0 diff --git a/apollo-router/src/query_planner/execution.rs b/apollo-router/src/query_planner/execution.rs index 21dcc605bb..363115b02b 100644 --- a/apollo-router/src/query_planner/execution.rs +++ b/apollo-router/src/query_planner/execution.rs @@ -21,6 +21,12 @@ use crate::json_ext::Value; use crate::json_ext::ValueExt; use crate::query_planner::FlattenNode; use crate::query_planner::Primary; +use crate::query_planner::CONDITION_ELSE_SPAN_NAME; +use crate::query_planner::CONDITION_IF_SPAN_NAME; +use crate::query_planner::CONDITION_SPAN_NAME; +use crate::query_planner::DEFER_DEFERRED_SPAN_NAME; +use crate::query_planner::DEFER_PRIMARY_SPAN_NAME; +use crate::query_planner::DEFER_SPAN_NAME; use crate::query_planner::FETCH_SPAN_NAME; use crate::query_planner::FLATTEN_SPAN_NAME; use crate::query_planner::PARALLEL_SPAN_NAME; @@ -107,45 +113,54 @@ impl PlanNode { PlanNode::Sequence { nodes } => { value = parent_value.clone(); errors = Vec::new(); - let span = tracing::info_span!(SEQUENCE_SPAN_NAME); - for node in nodes { - let (v, subselect, err) = node - .execute_recursively(parameters, current_dir, &value, sender.clone()) - .instrument(span.clone()) - .in_current_span() - .await; - value.deep_merge(v); - errors.extend(err.into_iter()); - subselection = subselect; + async { + for node in nodes { + let (v, subselect, err) = node + .execute_recursively( + parameters, + current_dir, + &value, + sender.clone(), + ) + .in_current_span() + .await; + value.deep_merge(v); + errors.extend(err.into_iter()); + subselection = subselect; + } } + .instrument( + tracing::info_span!(SEQUENCE_SPAN_NAME, "otel.kind" = %SpanKind::Internal), + ) + .await } PlanNode::Parallel { nodes } => { value = Value::default(); errors = Vec::new(); + async { + let mut stream: stream::FuturesUnordered<_> = nodes + .iter() + .map(|plan| { + plan.execute_recursively( + parameters, + current_dir, + parent_value, + sender.clone(), + ) + .in_current_span() + }) + .collect(); - let span = tracing::info_span!(PARALLEL_SPAN_NAME); - let mut stream: stream::FuturesUnordered<_> = nodes - .iter() - .map(|plan| { - plan.execute_recursively( - parameters, - current_dir, - parent_value, - sender.clone(), - ) - .instrument(span.clone()) - }) - .collect(); - - while let Some((v, _subselect, err)) = stream - .next() - .instrument(span.clone()) - .in_current_span() - .await - { - value.deep_merge(v); - errors.extend(err.into_iter()); + while let Some((v, _subselect, err)) = stream.next().in_current_span().await + { + value.deep_merge(v); + errors.extend(err.into_iter()); + } } + .instrument( + tracing::info_span!(PARALLEL_SPAN_NAME, "otel.kind" = %SpanKind::Internal), + ) + .await } PlanNode::Flatten(FlattenNode { path, node }) => { // Note that the span must be `info` as we need to pick this up in apollo tracing @@ -158,9 +173,7 @@ impl PlanNode { parent_value, sender, ) - .instrument( - tracing::info_span!(FLATTEN_SPAN_NAME, apollo_private.path = %current_dir), - ) + .instrument(tracing::info_span!(FLATTEN_SPAN_NAME, "graphql.path" = %current_dir, "otel.kind" = %SpanKind::Internal)) .await; value = v; @@ -200,66 +213,63 @@ impl PlanNode { }, deferred, } => { - let mut deferred_fetches: HashMap)>> = - HashMap::new(); - let mut futures = Vec::new(); - - let (primary_sender, _) = tokio::sync::broadcast::channel::(1); + value = parent_value.clone(); + errors = Vec::new(); + async { + let mut deferred_fetches: HashMap)>> = + HashMap::new(); + let mut futures = Vec::new(); - for deferred_node in deferred { - let fut = deferred_node.execute( - parameters, - parent_value, - sender.clone(), - &primary_sender, - &mut deferred_fetches, - ); + let (primary_sender, _) = tokio::sync::broadcast::channel::(1); - futures.push(fut); - } + for deferred_node in deferred { + let fut = deferred_node + .execute( + parameters, + parent_value, + sender.clone(), + &primary_sender, + &mut deferred_fetches, + ) + .in_current_span(); - tokio::task::spawn( - async move { - join_all(futures).await; + futures.push(fut); } - .in_current_span(), - ); - - value = parent_value.clone(); - errors = Vec::new(); - let span = tracing::info_span!("primary"); - if let Some(node) = node { - let (v, _subselect, err) = node - .execute_recursively( - &ExecutionParameters { - context: parameters.context, - service_factory: parameters.service_factory, - schema: parameters.schema, - supergraph_request: parameters.supergraph_request, - deferred_fetches: &deferred_fetches, - options: parameters.options, - query: parameters.query, - }, - current_dir, - &value, - sender, - ) - .instrument(span.clone()) - .in_current_span() - .await; - let _guard = span.enter(); - value.deep_merge(v); - errors.extend(err.into_iter()); - subselection = primary_subselection.clone(); - let _ = primary_sender.send(value.clone()); - } else { - let _guard = span.enter(); + tokio::task::spawn(async move { + join_all(futures).await; + }); - subselection = primary_subselection.clone(); + if let Some(node) = node { + let (v, _subselect, err) = node + .execute_recursively( + &ExecutionParameters { + context: parameters.context, + service_factory: parameters.service_factory, + schema: parameters.schema, + supergraph_request: parameters.supergraph_request, + deferred_fetches: &deferred_fetches, + options: parameters.options, + query: parameters.query, + }, + current_dir, + &value, + sender, + ) + .instrument(tracing::info_span!(DEFER_PRIMARY_SPAN_NAME, "otel.kind" = %SpanKind::Internal)) + .await; + value.deep_merge(v); + errors.extend(err.into_iter()); + subselection = primary_subselection.clone(); - let _ = primary_sender.send(value.clone()); + let _ = primary_sender.send(value.clone()); + } else { + subselection = primary_subselection.clone(); + let _ = primary_sender.send(value.clone()); + } } + .instrument(tracing::info_span!(DEFER_SPAN_NAME, "otel.kind" = %SpanKind::Internal)) + .await } PlanNode::Condition { condition, @@ -269,23 +279,37 @@ impl PlanNode { value = Value::default(); errors = Vec::new(); - let v = parameters - .query - .variable_value( - parameters - .supergraph_request - .body() - .operation_name - .as_deref(), - condition.as_str(), - ¶meters.supergraph_request.body().variables, - ) - .unwrap_or(&Value::Bool(true)); // the defer if clause is mandatory, and defaults to true - - if let &Value::Bool(true) = v { - //FIXME: should we show an error if the if_node was not present? - if let Some(node) = if_clause { - let span = tracing::info_span!("condition_if"); + async { + let v = parameters + .query + .variable_value( + parameters + .supergraph_request + .body() + .operation_name + .as_deref(), + condition.as_str(), + ¶meters.supergraph_request.body().variables, + ) + .unwrap_or(&Value::Bool(true)); // the defer if clause is mandatory, and defaults to true + + if let &Value::Bool(true) = v { + //FIXME: should we show an error if the if_node was not present? + if let Some(node) = if_clause { + let (v, subselect, err) = node + .execute_recursively( + parameters, + current_dir, + parent_value, + sender.clone(), + ) + .instrument(tracing::info_span!(CONDITION_IF_SPAN_NAME, "otel.kind" = %SpanKind::Internal)) + .await; + value.deep_merge(v); + errors.extend(err.into_iter()); + subselection = subselect; + } + } else if let Some(node) = else_clause { let (v, subselect, err) = node .execute_recursively( parameters, @@ -293,29 +317,19 @@ impl PlanNode { parent_value, sender.clone(), ) - .instrument(span.clone()) - .in_current_span() + .instrument(tracing::info_span!(CONDITION_ELSE_SPAN_NAME, "otel.kind" = %SpanKind::Internal)) .await; value.deep_merge(v); errors.extend(err.into_iter()); subselection = subselect; } - } else if let Some(node) = else_clause { - let span = tracing::info_span!("condition_else"); - let (v, subselect, err) = node - .execute_recursively( - parameters, - current_dir, - parent_value, - sender.clone(), - ) - .instrument(span.clone()) - .in_current_span() - .await; - value.deep_merge(v); - errors.extend(err.into_iter()); - subselection = subselect; } + .instrument(tracing::info_span!( + CONDITION_SPAN_NAME, + "graphql.condition" = condition, + "otel.kind" = %SpanKind::Internal + )) + .await } } @@ -374,7 +388,7 @@ impl DeferredNode { let query = parameters.query.clone(); let mut primary_receiver = primary_sender.subscribe(); let mut value = parent_value.clone(); - + let depends_json = serde_json::to_string(&self.depends).unwrap_or_default(); async move { let mut errors = Vec::new(); @@ -394,7 +408,6 @@ impl DeferredNode { } } - let span = tracing::info_span!("deferred"); let deferred_fetches = HashMap::new(); if let Some(node) = deferred_inner { @@ -413,8 +426,13 @@ impl DeferredNode { &value, tx.clone(), ) - .instrument(span.clone()) - .in_current_span() + .instrument(tracing::info_span!( + DEFER_DEFERRED_SPAN_NAME, + "graphql.label" = label, + "graphql.depends" = depends_json, + "graphql.path" = deferred_path.to_string(), + "otel.kind" = %SpanKind::Internal + )) .await; if !is_depends_empty { diff --git a/apollo-router/src/query_planner/mod.rs b/apollo-router/src/query_planner/mod.rs index 1163724e55..25a7d6a57e 100644 --- a/apollo-router/src/query_planner/mod.rs +++ b/apollo-router/src/query_planner/mod.rs @@ -20,6 +20,12 @@ pub(crate) const FETCH_SPAN_NAME: &str = "fetch"; pub(crate) const FLATTEN_SPAN_NAME: &str = "flatten"; pub(crate) const SEQUENCE_SPAN_NAME: &str = "sequence"; pub(crate) const PARALLEL_SPAN_NAME: &str = "parallel"; +pub(crate) const DEFER_SPAN_NAME: &str = "defer"; +pub(crate) const DEFER_PRIMARY_SPAN_NAME: &str = "defer_primary"; +pub(crate) const DEFER_DEFERRED_SPAN_NAME: &str = "defer_deferred"; +pub(crate) const CONDITION_SPAN_NAME: &str = "condition"; +pub(crate) const CONDITION_IF_SPAN_NAME: &str = "condition_if"; +pub(crate) const CONDITION_ELSE_SPAN_NAME: &str = "condition_else"; // The code resides in a separate submodule to allow writing a log filter activating it // separately from the query planner logs, as follows: diff --git a/apollo-router/src/query_planner/plan.rs b/apollo-router/src/query_planner/plan.rs index 873b6d4593..2635d081b9 100644 --- a/apollo-router/src/query_planner/plan.rs +++ b/apollo-router/src/query_planner/plan.rs @@ -132,17 +132,6 @@ impl PlanNode { } } - pub(crate) fn contains_condition_or_defer(&self) -> bool { - match self { - Self::Sequence { nodes } => nodes.iter().any(|n| n.contains_condition_or_defer()), - Self::Parallel { nodes } => nodes.iter().any(|n| n.contains_condition_or_defer()), - Self::Flatten(node) => node.node.contains_condition_or_defer(), - Self::Fetch(..) => false, - Self::Defer { .. } => true, - Self::Condition { .. } => true, - } - } - pub(crate) fn is_deferred( &self, operation: Option<&str>, diff --git a/apollo-router/tests/snapshots/integration_tests__traced_basic_composition.snap b/apollo-router/tests/snapshots/integration_tests__traced_basic_composition.snap index c528154c2d..0cb443e284 100644 --- a/apollo-router/tests/snapshots/integration_tests__traced_basic_composition.snap +++ b/apollo-router/tests/snapshots/integration_tests__traced_basic_composition.snap @@ -47,7 +47,7 @@ expression: get_spans() ], [ "apollo_private.graphql.variables", - "{\"reviewsForAuthorAuthorId\":[\"\"],\"topProductsFirst\":[\"\"]}" + "{\"reviewsForAuthorAuthorId\":\"\",\"topProductsFirst\":\"\"}" ], [ "apollo_private.http.request_headers", @@ -140,22 +140,10 @@ expression: get_spans() "name": "apollo_router::plugins::telemetry::execution", "record": { "entries": [ - [ - "graphql.document", - "{ topProducts { upc name reviews {id product { name } author { id name } } } }" - ], - [ - "graphql.operation.name", - "" - ], [ "otel.kind", "internal" ], - [ - "ftv1.do_not_sample_reason", - "" - ], [ "message", "dropping telemetry..." @@ -168,10 +156,7 @@ expression: get_spans() "module_path": "apollo_router::plugins::telemetry", "fields": { "names": [ - "graphql.document", - "graphql.operation.name", - "otel.kind", - "ftv1.do_not_sample_reason" + "otel.kind" ] } } @@ -180,14 +165,21 @@ expression: get_spans() "apollo_router::query_planner::execution::sequence": { "name": "apollo_router::query_planner::execution::sequence", "record": { - "entries": [], + "entries": [ + [ + "otel.kind", + "internal" + ] + ], "metadata": { "name": "sequence", "target": "apollo_router::query_planner::execution", "level": "INFO", "module_path": "apollo_router::query_planner::execution", "fields": { - "names": [] + "names": [ + "otel.kind" + ] } } }, @@ -399,8 +391,12 @@ expression: get_spans() "record": { "entries": [ [ - "apollo_private.path", + "graphql.path", "/topProducts/@" + ], + [ + "otel.kind", + "internal" ] ], "metadata": { @@ -410,7 +406,8 @@ expression: get_spans() "module_path": "apollo_router::query_planner::execution", "fields": { "names": [ - "apollo_private.path" + "graphql.path", + "otel.kind" ] } } @@ -623,14 +620,21 @@ expression: get_spans() "apollo_router::query_planner::execution::parallel": { "name": "apollo_router::query_planner::execution::parallel", "record": { - "entries": [], + "entries": [ + [ + "otel.kind", + "internal" + ] + ], "metadata": { "name": "parallel", "target": "apollo_router::query_planner::execution", "level": "INFO", "module_path": "apollo_router::query_planner::execution", "fields": { - "names": [] + "names": [ + "otel.kind" + ] } } }, @@ -640,8 +644,12 @@ expression: get_spans() "record": { "entries": [ [ - "apollo_private.path", + "graphql.path", "/topProducts/@/reviews/@/product" + ], + [ + "otel.kind", + "internal" ] ], "metadata": { @@ -651,7 +659,8 @@ expression: get_spans() "module_path": "apollo_router::query_planner::execution", "fields": { "names": [ - "apollo_private.path" + "graphql.path", + "otel.kind" ] } } @@ -866,8 +875,12 @@ expression: get_spans() "record": { "entries": [ [ - "apollo_private.path", + "graphql.path", "/topProducts/@/reviews/@/author" + ], + [ + "otel.kind", + "internal" ] ], "metadata": { @@ -877,7 +890,8 @@ expression: get_spans() "module_path": "apollo_router::query_planner::execution", "fields": { "names": [ - "apollo_private.path" + "graphql.path", + "otel.kind" ] } } diff --git a/apollo-router/tests/snapshots/integration_tests__traced_basic_request.snap b/apollo-router/tests/snapshots/integration_tests__traced_basic_request.snap index b375f05c41..bc33af8a03 100644 --- a/apollo-router/tests/snapshots/integration_tests__traced_basic_request.snap +++ b/apollo-router/tests/snapshots/integration_tests__traced_basic_request.snap @@ -47,7 +47,7 @@ expression: get_spans() ], [ "apollo_private.graphql.variables", - "{\"reviewsForAuthorAuthorId\":[\"\"],\"topProductsFirst\":[\"\"]}" + "{\"reviewsForAuthorAuthorId\":\"\",\"topProductsFirst\":\"\"}" ], [ "apollo_private.http.request_headers", @@ -140,22 +140,10 @@ expression: get_spans() "name": "apollo_router::plugins::telemetry::execution", "record": { "entries": [ - [ - "graphql.document", - "{ topProducts { name name2:name } }" - ], - [ - "graphql.operation.name", - "" - ], [ "otel.kind", "internal" ], - [ - "ftv1.do_not_sample_reason", - "" - ], [ "message", "dropping telemetry..." @@ -168,10 +156,7 @@ expression: get_spans() "module_path": "apollo_router::plugins::telemetry", "fields": { "names": [ - "graphql.document", - "graphql.operation.name", - "otel.kind", - "ftv1.do_not_sample_reason" + "otel.kind" ] } } diff --git a/xtask/src/commands/compliance.rs b/xtask/src/commands/compliance.rs index 4988c00df6..b93a94a901 100644 --- a/xtask/src/commands/compliance.rs +++ b/xtask/src/commands/compliance.rs @@ -12,7 +12,11 @@ use xtask::*; static LICENSES_HTML_PATH: &str = "licenses.html"; #[derive(Debug, StructOpt)] -pub struct Compliance {} +pub struct Compliance { + /// Do not run the compliance test + #[structopt(long)] + skip_compliance: bool, +} impl Compliance { pub fn run(&self) -> Result<()> { @@ -56,33 +60,37 @@ impl Compliance { } pub fn run_local(&self) -> Result<()> { - eprintln!("Checking generated licenses.html file..."); + if !self.skip_compliance { + eprintln!("Checking generated licenses.html file..."); - cargo!(["deny", "-L", "error", "check"]); + cargo!(["deny", "-L", "error", "check"]); - let licenses_html_before = Self::digest_for_license_file()?; + let licenses_html_before = Self::digest_for_license_file()?; - cargo!([ - "about", - "-L", - "error", - "generate", - "--workspace", - "-o", - "licenses.html", - "about.hbs", - ]); + cargo!([ + "about", + "-L", + "error", + "generate", + "--workspace", + "-o", + "licenses.html", + "about.hbs", + ]); - let licences_html_after = Self::digest_for_license_file()?; + let licences_html_after = Self::digest_for_license_file()?; - (licenses_html_before != licences_html_after).then(|| { - eprintln!( - "💅 licenses.html is now up to date. 💅\n\ + (licenses_html_before != licences_html_after).then(|| { + eprintln!( + "💅 licenses.html is now up to date. 💅\n\ Commit the changes and you should be good to go!" - ); - }); + ); + }); - Ok(()) + Ok(()) + } else { + Ok(()) + } } fn digest_for_license_file() -> Result> {