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  }