libp2p_server/
http_service.rs1use std::{
22 net::SocketAddr,
23 sync::{Arc, Mutex},
24};
25
26use axum::{extract::State, http::StatusCode, response::IntoResponse, routing::get, Router};
27use prometheus_client::{encoding::text::encode, registry::Registry};
28use tokio::net::TcpListener;
29
30const METRICS_CONTENT_TYPE: &str = "application/openmetrics-text;charset=utf-8;version=1.0.0";
31pub(crate) async fn metrics_server(
32 registry: Registry,
33 metrics_path: String,
34) -> Result<(), std::io::Error> {
35 let addr: SocketAddr = ([0, 0, 0, 0], 8888).into();
37 let service = MetricService::new(registry);
38 let server = Router::new()
39 .route(&metrics_path, get(respond_with_metrics))
40 .with_state(service);
41 let tcp_listener = TcpListener::bind(addr).await?;
42 let local_addr = tcp_listener.local_addr()?;
43 tracing::info!(metrics_server=%format!("http://{}{}", local_addr, metrics_path));
44 axum::serve(tcp_listener, server.into_make_service()).await?;
45 Ok(())
46}
47
48async fn respond_with_metrics(state: State<MetricService>) -> impl IntoResponse {
49 let mut sink = String::new();
50 let reg = state.get_reg();
51 encode(&mut sink, ®.lock().unwrap()).unwrap();
52
53 (
54 StatusCode::OK,
55 [(axum::http::header::CONTENT_TYPE, METRICS_CONTENT_TYPE)],
56 sink,
57 )
58}
59
60#[derive(Clone)]
61pub(crate) struct MetricService {
62 reg: Arc<Mutex<Registry>>,
63}
64
65type SharedRegistry = Arc<Mutex<Registry>>;
66
67impl MetricService {
68 fn new(reg: Registry) -> Self {
69 Self {
70 reg: Arc::new(Mutex::new(reg)),
71 }
72 }
73
74 fn get_reg(&self) -> SharedRegistry {
75 Arc::clone(&self.reg)
76 }
77}