@@ -6,15 +6,18 @@ use crate::{
66 NodeConfig , NodeState , key_manager:: load_and_decrypt_keypair, swarm_manager:: build_swarm,
77 wallet:: TaprootWallet ,
88} ;
9+ use actix_web:: { App , HttpResponse , HttpServer , web} ;
910use bitcoin:: Network ;
1011use grpc:: grpc_handler:: NodeControlService ;
12+ use metrics_exporter_prometheus:: { PrometheusBuilder , PrometheusHandle } ;
1113use std:: path:: { Path , PathBuf } ;
14+ use std:: sync:: Arc ;
1215use tokio:: sync:: broadcast;
1316use tonic:: transport:: Server ;
1417use tracing_appender:: rolling:: { RollingFileAppender , Rotation } ;
1518use tracing_subscriber:: { EnvFilter , fmt, prelude:: * } ;
1619
17- use std :: sync :: Arc ;
20+ type PrometheusHandler = Arc < PrometheusHandle > ;
1821
1922pub async fn start_node (
2023 config : NodeConfig ,
@@ -76,6 +79,43 @@ pub async fn start_node(
7679 tracing:: info!( "Logging initialized with console output only" ) ;
7780 }
7881
82+ let prometheus_handle: Arc < PrometheusHandle > = {
83+ let builder = PrometheusBuilder :: new ( ) ;
84+ Arc :: new (
85+ builder
86+ . install_recorder ( )
87+ . expect ( "failed to install Prometheus recorder" ) ,
88+ )
89+ } ;
90+
91+ let metrics_server_handle = tokio:: spawn ( async move {
92+ async fn metrics_endpoint ( handler : web:: Data < PrometheusHandler > ) -> HttpResponse {
93+ metrics:: counter!( "metrics_scrape_requests_total" ) . increment ( 1 ) ;
94+ HttpResponse :: Ok ( )
95+ . content_type ( "text/plain" )
96+ . body ( handler. render ( ) )
97+ }
98+
99+ async fn health_endpoint ( ) -> HttpResponse {
100+ HttpResponse :: Ok ( ) . content_type ( "text/plain" ) . body ( "OK" )
101+ }
102+
103+ tracing:: info!( "Starting metrics server on 0.0.0.0:8080" ) ;
104+
105+ let server = HttpServer :: new ( move || {
106+ App :: new ( )
107+ . app_data ( web:: Data :: new ( prometheus_handle. clone ( ) ) )
108+ . route ( "/metrics" , web:: get ( ) . to ( metrics_endpoint) )
109+ . route ( "/health" , web:: get ( ) . to ( health_endpoint) )
110+ } )
111+ . bind ( ( "0.0.0.0" , 8080 ) )
112+ . expect ( "Failed to bind metrics endpoint" ) ;
113+
114+ tracing:: info!( "Metrics server bound successfully, starting to serve" ) ;
115+
116+ server. run ( ) . await . expect ( "Metrics server failed" ) ;
117+ } ) ;
118+
79119 let keypair = match load_and_decrypt_keypair ( & config) {
80120 Ok ( kp) => kp,
81121 Err ( e) => {
@@ -218,6 +258,12 @@ pub async fn start_node(
218258 Err ( e) => tracing:: error!( "Chain interface error: {}" , e) ,
219259 }
220260 }
261+ result = metrics_server_handle => {
262+ match result {
263+ Ok ( ( ) ) => tracing:: info!( "Metrics server stopped" ) ,
264+ Err ( e) => tracing:: error!( "Metrics server error: {}" , e) ,
265+ }
266+ }
221267 }
222268
223269 Ok ( ( ) )
0 commit comments