@@ -37,6 +37,9 @@ use crate::{
3737
3838mod guarded_channel;
3939
40+ #[ cfg( feature = "metrics" ) ]
41+ mod metrics;
42+
4043// TODO: use this
4144// /// Number of addresses that are not active that we keep around per endpoint.
4245// ///
@@ -75,6 +78,9 @@ const APPLICATION_ABANDON_PATH: u8 = 30;
7578/// in a high frequency, and to keep data about previous path around for subsequent connections.
7679const ACTOR_MAX_IDLE_TIMEOUT : Duration = Duration :: from_secs ( 60 ) ;
7780
81+ /// Interval in which connection and path metrics are emitted.
82+ const METRICS_INTERVAL : Duration = Duration :: from_secs ( 10 ) ;
83+
7884/// A stream of events from all paths for all connections.
7985///
8086/// The connection is identified using [`ConnId`]. The event `Err` variant happens when the
@@ -220,6 +226,7 @@ impl EndpointStateActor {
220226 trace ! ( "actor started" ) ;
221227 let idle_timeout = MaybeFuture :: None ;
222228 tokio:: pin!( idle_timeout) ;
229+ let mut metrics_interval = time:: interval ( METRICS_INTERVAL ) ;
223230 loop {
224231 let scheduled_path_open = match self . scheduled_open_path {
225232 Some ( when) => MaybeFuture :: Some ( time:: sleep_until ( when) ) ,
@@ -262,6 +269,9 @@ impl EndpointStateActor {
262269 self . scheduled_holepunch = None ;
263270 self . trigger_holepunching( ) . await ;
264271 }
272+ _ = metrics_interval. tick( ) => {
273+ self . record_metrics( ) ;
274+ }
265275 _ = & mut idle_timeout => {
266276 if self . connections. is_empty( ) && inbox. close_if_idle( ) {
267277 trace!( "idle timeout expired and still idle: terminate actor" ) ;
@@ -384,7 +394,8 @@ impl EndpointStateActor {
384394 paths : Default :: default ( ) ,
385395 open_paths : Default :: default ( ) ,
386396 path_ids : Default :: default ( ) ,
387- transport_summary : TransportSummary :: default ( ) ,
397+ #[ cfg( feature = "metrics" ) ]
398+ metrics : Default :: default ( ) ,
388399 } )
389400 . into_mut ( ) ;
390401
@@ -571,8 +582,10 @@ impl EndpointStateActor {
571582
572583 fn handle_connection_close ( & mut self , conn_id : ConnId ) {
573584 if let Some ( state) = self . connections . remove ( & conn_id) {
574- self . metrics . num_conns_closed . inc ( ) ;
575- state. transport_summary . record ( & self . metrics ) ;
585+ #[ cfg( feature = "metrics" ) ]
586+ state. metrics . record_closed ( & self . metrics ) ;
587+ #[ cfg( not( feature = "metrics" ) ) ]
588+ let _ = state;
576589 }
577590 if self . connections . is_empty ( ) {
578591 trace ! ( "last connection closed - clearing selected_path" ) ;
@@ -1021,6 +1034,13 @@ impl EndpointStateActor {
10211034 }
10221035 }
10231036 }
1037+
1038+ fn record_metrics ( & mut self ) {
1039+ #[ cfg( feature = "metrics" ) ]
1040+ for state in self . connections . values_mut ( ) {
1041+ state. record_metrics_periodic ( & self . metrics , self . selected_path . get ( ) ) ;
1042+ }
1043+ }
10241044}
10251045
10261046/// Messages to send to the [`EndpointStateActor`].
@@ -1123,8 +1143,11 @@ struct ConnectionState {
11231143 open_paths : FxHashMap < PathId , transports:: Addr > ,
11241144 /// Reverse map of [`Self::paths].
11251145 path_ids : FxHashMap < transports:: Addr , PathId > ,
1126- /// Summary over transports used in this connection, for metrics tracking.
1127- transport_summary : TransportSummary ,
1146+ /// Tracker for stateful metrics for this connection and its paths
1147+ ///
1148+ /// Feature-gated on the `metrics` feature because it increases memory use.
1149+ #[ cfg( feature = "metrics" ) ]
1150+ metrics : self :: metrics:: MetricsTracker ,
11281151}
11291152
11301153impl ConnectionState {
@@ -1136,7 +1159,8 @@ impl ConnectionState {
11361159
11371160 /// Tracks an open path for the connection.
11381161 fn add_open_path ( & mut self , remote : transports:: Addr , path_id : PathId ) {
1139- self . transport_summary . add_path ( & remote) ;
1162+ #[ cfg( feature = "metrics" ) ]
1163+ self . metrics . add_path ( path_id, & remote) ;
11401164 self . paths . insert ( path_id, remote. clone ( ) ) ;
11411165 self . open_paths . insert ( path_id, remote. clone ( ) ) ;
11421166 self . path_ids . insert ( remote, path_id) ;
@@ -1149,11 +1173,15 @@ impl ConnectionState {
11491173 self . path_ids . remove ( & addr) ;
11501174 }
11511175 self . open_paths . remove ( path_id) ;
1176+ #[ cfg( feature = "metrics" ) ]
1177+ self . metrics . remove_path ( path_id) ;
11521178 }
11531179
11541180 /// Removes the path from the open paths.
11551181 fn remove_open_path ( & mut self , path_id : & PathId ) {
11561182 self . open_paths . remove ( path_id) ;
1183+ #[ cfg( feature = "metrics" ) ]
1184+ self . metrics . remove_path ( path_id) ;
11571185
11581186 self . update_pub_path_info ( ) ;
11591187 }
@@ -1173,6 +1201,19 @@ impl ConnectionState {
11731201
11741202 self . pub_open_paths . set ( new) . ok ( ) ;
11751203 }
1204+
1205+ #[ cfg( feature = "metrics" ) ]
1206+ fn record_metrics_periodic (
1207+ & mut self ,
1208+ metrics : & MagicsockMetrics ,
1209+ selected_path : Option < transports:: Addr > ,
1210+ ) {
1211+ let Some ( conn) = self . handle . upgrade ( ) else {
1212+ return ;
1213+ } ;
1214+ self . metrics
1215+ . record_periodic ( metrics, & conn, & self . open_paths , selected_path) ;
1216+ }
11761217}
11771218
11781219/// Watcher for the open paths and selected transmission path in a connection.
@@ -1383,41 +1424,3 @@ impl Future for OnClosed {
13831424 Poll :: Ready ( self . conn_id )
13841425 }
13851426}
1386-
1387- /// Used for metrics tracking.
1388- #[ derive( Debug , Clone , Copy , Default ) ]
1389- enum TransportSummary {
1390- #[ default]
1391- None ,
1392- IpOnly ,
1393- RelayOnly ,
1394- IpAndRelay ,
1395- }
1396-
1397- impl TransportSummary {
1398- fn add_path ( & mut self , addr : & transports:: Addr ) {
1399- use transports:: Addr ;
1400- * self = match ( * self , addr) {
1401- ( TransportSummary :: None | TransportSummary :: IpOnly , Addr :: Ip ( _) ) => Self :: IpOnly ,
1402- ( TransportSummary :: None | TransportSummary :: RelayOnly , Addr :: Relay ( _, _) ) => {
1403- Self :: RelayOnly
1404- }
1405- _ => Self :: IpAndRelay ,
1406- }
1407- }
1408-
1409- fn record ( & self , metrics : & MagicsockMetrics ) {
1410- match self {
1411- TransportSummary :: IpOnly => {
1412- metrics. num_conns_transport_ip_only . inc ( ) ;
1413- }
1414- TransportSummary :: RelayOnly => {
1415- metrics. num_conns_transport_relay_only . inc ( ) ;
1416- }
1417- TransportSummary :: IpAndRelay => {
1418- metrics. num_conns_transport_ip_and_relay . inc ( ) ;
1419- }
1420- TransportSummary :: None => { }
1421- }
1422- }
1423- }
0 commit comments