diff --git a/backend/graph-proxy/src/graphql/mod.rs b/backend/graph-proxy/src/graphql/mod.rs index e996eeb61..7d9c2d955 100644 --- a/backend/graph-proxy/src/graphql/mod.rs +++ b/backend/graph-proxy/src/graphql/mod.rs @@ -22,8 +22,8 @@ use self::{ workflows::{Workflow, WorkflowsQuery}, }; use async_graphql::{ - parser::parse_query, Context, InputObject, MergedObject, MergedSubscription, Object, Schema, - SchemaBuilder, SimpleObject, Union, ID, + extensions::Analyzer, parser::parse_query, Context, InputObject, MergedObject, + MergedSubscription, Object, Schema, SchemaBuilder, SimpleObject, Union, Value, ID, }; use async_graphql_axum::{GraphQLRequest, GraphQLResponse}; use axum::extract::State; @@ -47,6 +47,7 @@ pub fn root_schema_builder() -> SchemaBuilder { Subscription::default(), ) .enable_federation() + .extension(Analyzer) } /// The root query of the service @@ -158,7 +159,23 @@ pub async fn graphql_handler( }; let auth_token = auth_token_header.map(|header| header.0); - let response = state.schema.execute(query.data(auth_token)).await; + let mut response = state.schema.execute(query.data(auth_token)).await; + if let Some(Value::Object(analyzer)) = response.extensions.remove("analyzer") { + let depth = analyzer.get("depth").and_then(|value| match value { + Value::Number(number) => number.as_u64(), + _ => None, + }); + if let Some(depth) = depth { + state.metrics_state.query_depth.record(depth, &[]); + } + let complexity = analyzer.get("complexity").and_then(|value| match value { + Value::Number(number) => number.as_u64(), + _ => None, + }); + if let Some(complexity) = complexity { + state.metrics_state.query_complexity.record(complexity, &[]); + } + } let elapsed_ms = start.elapsed().as_secs_f64() * 1000.0; let status = if response.errors.is_empty() { "ok" diff --git a/backend/graph-proxy/src/metrics.rs b/backend/graph-proxy/src/metrics.rs index c65e4430c..236ef4cb2 100644 --- a/backend/graph-proxy/src/metrics.rs +++ b/backend/graph-proxy/src/metrics.rs @@ -15,6 +15,10 @@ pub struct Metrics { pub request_duration_ms: Histogram, /// Total errors on querys and mutations pub total_errors: Counter, + /// Query depth + pub query_depth: Histogram, + /// Query complexity + pub query_complexity: Histogram, } impl Metrics { @@ -38,10 +42,22 @@ impl Metrics { .with_description("The total errors on all querys and mutations.") .build(); + let query_depth = meter + .u64_histogram("graph_proxy_query_depth") + .with_description("GraphQL query depth") + .build(); + + let query_complexity = meter + .u64_histogram("graph_proxy_query_complexity") + .with_description("GraphQL query complexity") + .build(); + Metrics { total_requests, request_duration_ms, total_errors, + query_depth, + query_complexity, } } }