lib.rs
1 use std::net::SocketAddr; 2 3 use axum::http::StatusCode; 4 use axum::routing::get; 5 use axum::Router; 6 use fedimint_core::task::{TaskGroup, TaskShutdownToken}; 7 pub use lazy_static::lazy_static; 8 use prometheus::Registry; 9 pub use prometheus::{ 10 self, histogram_opts, opts, register_histogram_with_registry, 11 register_int_counter_vec_with_registry, Encoder, Gauge, GaugeVec, Histogram, HistogramVec, 12 IntCounter, IntCounterVec, TextEncoder, 13 }; 14 use tokio::net::TcpListener; 15 use tracing::error; 16 17 lazy_static! { 18 pub static ref REGISTRY: Registry = Registry::new_custom(Some("fm".into()), None).unwrap(); 19 pub static ref AMOUNTS_BUCKETS_SATS: Vec<f64> = vec![ 20 0.0, 21 0.1, 22 1.0, 23 10.0, 24 100.0, 25 1000.0, 26 10000.0, 27 100000.0, 28 1000000.0, 29 10000000.0, 30 100000000.0 31 ]; 32 } 33 34 async fn get_metrics() -> (StatusCode, String) { 35 let metric_families = REGISTRY.gather(); 36 let result = || -> anyhow::Result<String> { 37 let mut buffer = Vec::new(); 38 let encoder = TextEncoder::new(); 39 encoder.encode(&metric_families, &mut buffer)?; 40 Ok(String::from_utf8(buffer)?) 41 }; 42 match result() { 43 Ok(result) => (StatusCode::OK, result), 44 Err(e) => (StatusCode::INTERNAL_SERVER_ERROR, format!("{e:?}")), 45 } 46 } 47 48 pub async fn run_api_server( 49 bind_address: SocketAddr, 50 task_group: TaskGroup, 51 ) -> anyhow::Result<TaskShutdownToken> { 52 let app = Router::new().route("/metrics", get(get_metrics)); 53 let listener = TcpListener::bind(bind_address).await?; 54 let serve = axum::serve(listener, app.into_make_service()); 55 56 let handle = task_group.make_handle(); 57 let shutdown_rx = handle.make_shutdown_rx().await; 58 task_group.spawn("Metrics Api", move |_| async move { 59 let graceful = serve.with_graceful_shutdown(async { 60 shutdown_rx.await; 61 }); 62 63 if let Err(e) = graceful.await { 64 error!("Error shutting down metrics api: {e:?}"); 65 } 66 }); 67 let shutdown_receiver = handle.make_shutdown_rx().await; 68 69 Ok(shutdown_receiver) 70 }