11use axum:: { extract:: State as AxumState , routing:: get, Json , Router } ;
22use core:: net:: IpAddr ;
3- use metrics:: { Key , Label , Recorder } ;
4- use metrics_exporter_prometheus:: PrometheusBuilder ;
3+ use metrics:: { counter , gauge , Label } ;
4+ use metrics_exporter_prometheus:: PrometheusHandle ;
55use serde:: { Deserialize , Serialize } ;
66
7- use risotto_lib:: { state:: AsyncState , state_store:: store:: StateStore } ;
8-
9- static METADATA : metrics:: Metadata =
10- metrics:: Metadata :: new ( module_path ! ( ) , metrics:: Level :: INFO , Some ( module_path ! ( ) ) ) ;
7+ use risotto_lib:: { state:: AsyncState , state_store:: store:: StateStore , statistics:: AsyncStatistics } ;
118
129#[ derive( Debug , Serialize , Deserialize ) ]
1310struct APIRouter {
@@ -24,28 +21,38 @@ struct APIPeer {
2421
2522struct AppState < T : StateStore > {
2623 state : Option < AsyncState < T > > ,
24+ statistics : AsyncStatistics ,
25+ prom_handle : PrometheusHandle ,
2726}
2827
2928impl < T : StateStore > Clone for AppState < T > {
3029 fn clone ( & self ) -> Self {
3130 Self {
3231 state : self . state . clone ( ) ,
32+ statistics : self . statistics . clone ( ) ,
33+ prom_handle : self . prom_handle . clone ( ) ,
3334 }
3435 }
3536}
3637
37- pub fn app < T : StateStore > ( state : Option < AsyncState < T > > ) -> Router {
38- let app_state = AppState { state } ;
39-
38+ pub fn app < T : StateStore > (
39+ state : Option < AsyncState < T > > ,
40+ statistics : AsyncStatistics ,
41+ prom_handle : PrometheusHandle ,
42+ ) -> Router {
43+ let app_state = AppState {
44+ state,
45+ statistics,
46+ prom_handle,
47+ } ;
4048 Router :: new ( )
4149 . route ( "/" , get ( root) . with_state ( app_state. clone ( ) ) )
4250 . route ( "/metrics" , get ( metrics) . with_state ( app_state. clone ( ) ) )
4351}
4452
4553async fn format < T : StateStore > ( state : AsyncState < T > ) -> Vec < APIRouter > {
4654 let mut api_routers: Vec < APIRouter > = Vec :: new ( ) ;
47- let state = state. lock ( ) . unwrap ( ) ;
48-
55+ let state = state. lock ( ) . await ;
4956 for ( router_addr, peer_addr, update_prefix) in state. get_all ( ) . unwrap ( ) {
5057 // Find the router in the list of routers
5158 let mut router = None ;
@@ -102,7 +109,7 @@ async fn format<T: StateStore>(state: AsyncState<T>) -> Vec<APIRouter> {
102109}
103110
104111async fn root < T : StateStore > (
105- AxumState ( AppState { state } ) : AxumState < AppState < T > > ,
112+ AxumState ( AppState { state, .. } ) : AxumState < AppState < T > > ,
106113) -> Json < Vec < APIRouter > > {
107114 match state. as_ref ( ) {
108115 Some ( state) => {
@@ -113,45 +120,52 @@ async fn root<T: StateStore>(
113120 }
114121}
115122
116- async fn metrics < T : StateStore > ( AxumState ( AppState { state } ) : AxumState < AppState < T > > ) -> String {
117- if state. is_none ( ) {
118- return String :: new ( ) ;
119- }
120-
121- let state = state. unwrap ( ) ;
122-
123- let recorder = PrometheusBuilder :: new ( ) . build_recorder ( ) ;
124- let api_routers = format ( state) . await ;
125-
126- recorder. describe_gauge (
127- "risotto_bgp_peers" . into ( ) ,
128- None ,
129- "Number of BGP peers per router" . into ( ) ,
130- ) ;
131- for api_router in & api_routers {
132- let labels = vec ! [ Label :: new( "router" , api_router. router_addr. to_string( ) ) ] ;
133- let key = Key :: from_parts ( "risotto_bgp_peers" , labels) ;
134- recorder
135- . register_gauge ( & key, & METADATA )
136- . set ( api_router. peers . len ( ) as f64 ) ;
137- }
123+ async fn metrics < T : StateStore > (
124+ AxumState ( AppState {
125+ state,
126+ statistics,
127+ prom_handle,
128+ } ) : AxumState < AppState < T > > ,
129+ ) -> String {
130+ // Set the state metrics if enabled
131+ if !state. is_none ( ) {
132+ let state = state. unwrap ( ) ;
133+ let api_routers = format ( state) . await ;
134+
135+ for api_router in & api_routers {
136+ let labels = vec ! [ Label :: new( "router" , api_router. router_addr. to_string( ) ) ] ;
137+ gauge ! ( "risotto_state_bgp_peers" , labels) . set ( api_router. peers . len ( ) as f64 ) ;
138+ }
138139
139- recorder. describe_gauge (
140- "risotto_bgp_updates" . into ( ) ,
141- None ,
142- "Number of BGP updates per (router, peer)" . into ( ) ,
143- ) ;
144- for api_router in & api_routers {
145- for api_peer in & api_router. peers {
146- let total = api_peer. ipv4 + api_peer. ipv6 ;
147- let labels = vec ! [
148- Label :: new( "router" , api_router. router_addr. to_string( ) ) ,
149- Label :: new( "peer" , api_peer. peer_addr. to_string( ) ) ,
150- ] ;
151- let key = Key :: from_parts ( "risotto_bgp_updates" , labels) ;
152- recorder. register_gauge ( & key, & METADATA ) . set ( total as f64 ) ;
140+ for api_router in & api_routers {
141+ for api_peer in & api_router. peers {
142+ let total = api_peer. ipv4 + api_peer. ipv6 ;
143+ let labels = vec ! [
144+ Label :: new( "router" , api_router. router_addr. to_string( ) ) ,
145+ Label :: new( "peer" , api_peer. peer_addr. to_string( ) ) ,
146+ ] ;
147+ gauge ! ( "risotto_state_bgp_updates" , labels) . set ( total as f64 ) ;
148+ }
153149 }
154150 }
155151
156- recorder. handle ( ) . render ( )
152+ // Set the statistics metrics
153+ let statistics = statistics. lock ( ) . await ;
154+ let metric_name = "risotto_bmp_messages_total" ;
155+ counter ! ( metric_name, vec![ Label :: new( "type" , "initiation" ) ] )
156+ . absolute ( statistics. rx_bmp_initiation as u64 ) ;
157+ counter ! ( metric_name, vec![ Label :: new( "type" , "peer_up" ) ] )
158+ . absolute ( statistics. rx_bmp_peer_up as u64 ) ;
159+ counter ! ( metric_name, vec![ Label :: new( "type" , "route_monitoring" ) ] )
160+ . absolute ( statistics. rx_bmp_route_monitoring as u64 ) ;
161+ counter ! ( metric_name, vec![ Label :: new( "type" , "route_mirroring" ) ] )
162+ . absolute ( statistics. rx_bmp_route_mirroring as u64 ) ;
163+ counter ! ( metric_name, vec![ Label :: new( "type" , "peer_down" ) ] )
164+ . absolute ( statistics. rx_bmp_peer_down as u64 ) ;
165+ counter ! ( metric_name, vec![ Label :: new( "type" , "termination" ) ] )
166+ . absolute ( statistics. rx_bmp_termination as u64 ) ;
167+ counter ! ( metric_name, vec![ Label :: new( "type" , "stats_report" ) ] )
168+ . absolute ( statistics. rx_bmp_stats_report as u64 ) ;
169+
170+ prom_handle. render ( )
157171}
0 commit comments