@@ -17,7 +17,7 @@ use crate::datafusion::physical_plan::merge::{
1717} ;
1818use crate :: datafusion:: rewriters:: session_context:: SessionContextExprRewriter ;
1919use crate :: error:: { OperationOn , OperationType } ;
20- use crate :: models:: { QueryContext , QueryResult } ;
20+ use crate :: models:: { QueryContext , QueryMetric , QueryResult , metrics_set_to_json } ;
2121use catalog:: table:: { CachingTable , IcebergTableBuilder } ;
2222use catalog_metastore:: {
2323 AwsAccessKeyCredentials , AwsCredentials , FileVolume , Metastore , S3TablesVolume , S3Volume ,
@@ -68,7 +68,7 @@ use datafusion_expr::{
6868} ;
6969use datafusion_iceberg:: DataFusionTable ;
7070use datafusion_iceberg:: table:: DataFusionTableConfigBuilder ;
71- use datafusion_physical_plan:: collect;
71+ use datafusion_physical_plan:: { ExecutionPlan , collect} ;
7272use functions:: semi_structured:: variant:: visitors:: visit_all;
7373use functions:: session_params:: SessionProperty ;
7474use functions:: visitors:: {
@@ -105,6 +105,7 @@ use std::ops::ControlFlow;
105105use std:: result:: Result as StdResult ;
106106use std:: str:: FromStr ;
107107use std:: sync:: Arc ;
108+ use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
108109use tracing:: Instrument ;
109110use tracing_attributes:: instrument;
110111use url:: Url ;
@@ -2130,11 +2131,24 @@ impl UserQuery {
21302131 . await
21312132 . context ( ex_error:: DataFusionSnafu ) ?;
21322133 let mut schema = df. schema ( ) . as_arrow ( ) . clone ( ) ;
2133- let records = df. collect ( ) . await . context ( ex_error:: DataFusionSnafu ) ?;
2134+ let physical_plan = df
2135+ . create_physical_plan ( )
2136+ . await
2137+ . context ( ex_error:: DataFusionSnafu ) ?;
2138+ let task_ctx = session. ctx . task_ctx ( ) ;
2139+ let metrics_plan = Arc :: clone ( & physical_plan) ;
2140+ let records = collect ( physical_plan, task_ctx)
2141+ . await
2142+ . context ( ex_error:: DataFusionSnafu ) ?;
21342143 if !records. is_empty ( ) {
21352144 schema = records[ 0 ] . schema ( ) . as_ref ( ) . clone ( ) ;
21362145 }
2137- Ok :: < QueryResult , Error > ( QueryResult :: new ( records, Arc :: new ( schema) ) )
2146+ let metrics = build_plan_metrics ( & metrics_plan) ;
2147+ Ok :: < QueryResult , Error > ( QueryResult :: new_with_metrics (
2148+ records,
2149+ Arc :: new ( schema) ,
2150+ metrics,
2151+ ) )
21382152 }
21392153
21402154 #[ instrument( name = "UserQuery::execute_sql" , level = "debug" , skip( self ) , err, ret) ]
@@ -2164,19 +2178,30 @@ impl UserQuery {
21642178 span : tracing:: Span ,
21652179 ) -> Result < QueryResult > {
21662180 let mut schema = plan. schema ( ) . as_arrow ( ) . clone ( ) ;
2167- let records = session
2181+ let df = session
21682182 . ctx
21692183 . execute_logical_plan ( plan)
21702184 . await
2171- . context ( ex_error:: DataFusionSnafu ) ?
2172- . collect ( )
2185+ . context ( ex_error:: DataFusionSnafu ) ?;
2186+ let physical_plan = df
2187+ . create_physical_plan ( )
2188+ . await
2189+ . context ( ex_error:: DataFusionSnafu ) ?;
2190+ let task_ctx = session. ctx . task_ctx ( ) ;
2191+ let metrics_plan = Arc :: clone ( & physical_plan) ;
2192+ let records = collect ( physical_plan, task_ctx)
21732193 . instrument ( span)
21742194 . await
21752195 . context ( ex_error:: DataFusionSnafu ) ?;
21762196 if !records. is_empty ( ) {
21772197 schema = records[ 0 ] . schema ( ) . as_ref ( ) . clone ( ) ;
21782198 }
2179- Ok :: < QueryResult , Error > ( QueryResult :: new ( records, Arc :: new ( schema) ) )
2199+ let metrics = build_plan_metrics ( & metrics_plan) ;
2200+ Ok :: < QueryResult , Error > ( QueryResult :: new_with_metrics (
2201+ records,
2202+ Arc :: new ( schema) ,
2203+ metrics,
2204+ ) )
21802205 }
21812206
21822207 async fn execute_logical_plan ( & self , plan : LogicalPlan ) -> Result < QueryResult > {
@@ -2221,13 +2246,19 @@ impl UserQuery {
22212246 . optimize ( physical_plan, & ConfigOptions :: new ( ) )
22222247 . context ( ex_error:: DataFusionSnafu ) ?;
22232248 }
2249+ let metrics_plan = Arc :: clone ( & physical_plan) ;
22242250 let records = collect ( physical_plan, Arc :: new ( task_ctx) )
22252251 . await
22262252 . context ( ex_error:: DataFusionSnafu ) ?;
22272253 if !records. is_empty ( ) {
22282254 schema = records[ 0 ] . schema ( ) . as_ref ( ) . clone ( ) ;
22292255 }
2230- Ok :: < QueryResult , Error > ( QueryResult :: new ( records, Arc :: new ( schema) ) )
2256+ let metrics = build_plan_metrics ( & metrics_plan) ;
2257+ Ok :: < QueryResult , Error > ( QueryResult :: new_with_metrics (
2258+ records,
2259+ Arc :: new ( schema) ,
2260+ metrics,
2261+ ) )
22312262 }
22322263
22332264 #[ instrument(
@@ -3549,3 +3580,26 @@ fn normalize_resolved_ref(table_ref: &ResolvedTableReference) -> ResolvedTableRe
35493580 table : Arc :: from ( table_ref. table . to_ascii_lowercase ( ) ) ,
35503581 }
35513582}
3583+
3584+ fn build_plan_metrics ( plan : & Arc < dyn ExecutionPlan > ) -> Vec < QueryMetric > {
3585+ let counter = AtomicUsize :: new ( 0 ) ;
3586+ let mut metrics = Vec :: new ( ) ;
3587+ collect_plan_metrics ( plan, None , & counter, & mut metrics) ;
3588+ metrics
3589+ }
3590+
3591+ fn collect_plan_metrics (
3592+ plan : & Arc < dyn ExecutionPlan > ,
3593+ parent : Option < usize > ,
3594+ counter : & AtomicUsize ,
3595+ out : & mut Vec < QueryMetric > ,
3596+ ) {
3597+ let node_id = counter. fetch_add ( 1 , Ordering :: SeqCst ) ;
3598+ let metrics_json = metrics_set_to_json ( plan. metrics ( ) ) ;
3599+
3600+ out. push ( QueryMetric :: new ( node_id, parent, plan. name ( ) , metrics_json) ) ;
3601+
3602+ for child in plan. children ( ) {
3603+ collect_plan_metrics ( child, Some ( node_id) , counter, out) ;
3604+ }
3605+ }
0 commit comments