11use  crate :: argconv:: * ; 
22use  crate :: batch:: CassBatch ; 
33use  crate :: cass_error:: * ; 
4+ use  crate :: cass_metrics_types:: CassMetrics ; 
45use  crate :: cass_types:: get_column_type; 
56use  crate :: cluster:: CassCluster ; 
67use  crate :: cluster:: build_session_builder; 
@@ -19,6 +20,7 @@ use scylla::client::session_builder::SessionBuilder;
1920use  scylla:: cluster:: metadata:: ColumnType ; 
2021use  scylla:: errors:: ExecutionError ; 
2122use  scylla:: frame:: types:: Consistency ; 
23+ use  scylla:: observability:: metrics:: MetricsError ; 
2224use  scylla:: response:: PagingStateResponse ; 
2325use  scylla:: response:: query_result:: QueryResult ; 
2426use  scylla:: statement:: unprepared:: Statement ; 
@@ -571,6 +573,91 @@ pub unsafe extern "C" fn cass_session_get_schema_meta(
571573    BoxFFI :: into_ptr ( Box :: new ( CassSchemaMeta  {  keyspaces } ) ) 
572574} 
573575
576+ #[ unsafe( no_mangle) ]  
577+ pub  unsafe  extern  "C"  fn  cass_session_get_metrics ( 
578+     session_raw :  CassBorrowedSharedPtr < CassSession ,  CConst > , 
579+     metrics :  * mut  CassMetrics , 
580+ )  { 
581+     let  Some ( maybe_session_lock)  = ArcFFI :: as_ref ( session_raw)  else  { 
582+         tracing:: error!( "Provided null session pointer to cass_session_get_metrics!" ) ; 
583+         return ; 
584+     } ; 
585+     if  metrics. is_null ( )  { 
586+         tracing:: error!( "Provided null metrics pointer to cass_session_get_metrics!" ) ; 
587+         return ; 
588+     } 
589+ 
590+     let  maybe_session_guard = maybe_session_lock. blocking_read ( ) ; 
591+     let  maybe_session = maybe_session_guard. as_ref ( ) ; 
592+     let  Some ( session)  = maybe_session else  { 
593+         tracing:: warn!( "Attempted to get metrics before connecting session object" ) ; 
594+         return ; 
595+     } ; 
596+ 
597+     let  rust_metrics = session. session . get_metrics ( ) ; 
598+     // TODO (rust-driver): Add Snapshot::default() or Snapshot::empty() with 0-initialized snapshot. 
599+     let  ( 
600+         min, 
601+         max, 
602+         mean, 
603+         stddev, 
604+         median, 
605+         percentile_75, 
606+         percentile_95, 
607+         percentile_98, 
608+         percentile_99, 
609+         percentile_99_9, 
610+     )  = match  rust_metrics. get_snapshot ( )  { 
611+         Ok ( snapshot)  => ( 
612+             snapshot. min , 
613+             snapshot. max , 
614+             snapshot. mean , 
615+             snapshot. stddev , 
616+             snapshot. median , 
617+             snapshot. percentile_75 , 
618+             snapshot. percentile_95 , 
619+             snapshot. percentile_98 , 
620+             snapshot. percentile_99 , 
621+             snapshot. percentile_99_9 , 
622+         ) , 
623+         // Histogram is empty, but we don't want to return because there 
624+         // are other metrics that don't depend on histogram. 
625+         Err ( MetricsError :: Empty )  => ( 0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ,  0 ) , 
626+         Err ( e)  => { 
627+             tracing:: error!( "Failed to get metrics snapshot: {}" ,  e) ; 
628+             return ; 
629+         } 
630+     } ; 
631+ 
632+     const  MILLIS_TO_MICROS :  u64  = 1000 ; 
633+     // SAFETY: We assume that user provided valid CassMetrics pointer. 
634+     unsafe  { 
635+         ( * metrics) . requests . min  = min *  MILLIS_TO_MICROS ; 
636+         ( * metrics) . requests . max  = max *  MILLIS_TO_MICROS ; 
637+         ( * metrics) . requests . mean  = mean *  MILLIS_TO_MICROS ; 
638+         ( * metrics) . requests . stddev  = stddev *  MILLIS_TO_MICROS ; 
639+         ( * metrics) . requests . median  = median *  MILLIS_TO_MICROS ; 
640+         ( * metrics) . requests . percentile_75th  = percentile_75 *  MILLIS_TO_MICROS ; 
641+         ( * metrics) . requests . percentile_95th  = percentile_95 *  MILLIS_TO_MICROS ; 
642+         ( * metrics) . requests . percentile_98th  = percentile_98 *  MILLIS_TO_MICROS ; 
643+         ( * metrics) . requests . percentile_99th  = percentile_99 *  MILLIS_TO_MICROS ; 
644+         ( * metrics) . requests . percentile_999th  = percentile_99_9 *  MILLIS_TO_MICROS ; 
645+         ( * metrics) . requests . mean_rate  = rust_metrics. get_mean_rate ( ) ; 
646+         ( * metrics) . requests . one_minute_rate  = rust_metrics. get_one_minute_rate ( ) ; 
647+         ( * metrics) . requests . five_minute_rate  = rust_metrics. get_five_minute_rate ( ) ; 
648+         ( * metrics) . requests . fifteen_minute_rate  = rust_metrics. get_fifteen_minute_rate ( ) ; 
649+ 
650+         ( * metrics) . stats . total_connections  = rust_metrics. get_total_connections ( ) ; 
651+         ( * metrics) . stats . available_connections  = 0 ;  // Deprecated 
652+         ( * metrics) . stats . exceeded_pending_requests_water_mark  = 0 ;  // Deprecated 
653+         ( * metrics) . stats . exceeded_write_bytes_water_mark  = 0 ;  // Deprecated 
654+ 
655+         ( * metrics) . errors . connection_timeouts  = rust_metrics. get_connection_timeouts ( ) ; 
656+         ( * metrics) . errors . pending_request_timeouts  = 0 ;  // Deprecated 
657+         ( * metrics) . errors . request_timeouts  = rust_metrics. get_request_timeouts ( ) ; 
658+     } 
659+ } 
660+ 
574661#[ cfg( test) ]  
575662mod  tests { 
576663    use  rusty_fork:: rusty_fork_test; 
0 commit comments