tempo_commonware_node/
metrics.rs

1use std::net::SocketAddr;
2
3use axum::{
4    Extension, Router,
5    body::Body,
6    http::{Response, StatusCode, header},
7    routing::get,
8};
9use commonware_runtime::{Handle, Metrics as _, Spawner as _, tokio::Context};
10use eyre::WrapErr as _;
11use tokio::net::TcpListener;
12
13/// Installs a metrics server so that commonware can publish its metrics.
14///
15/// This is lifted straight from [`commonware_runtime::tokio::telemetry::init`],
16/// because it also wants to install a tracing subscriber, which clashes with
17/// reth ethereum cli doing the same thing.
18pub fn install(context: Context, listen_addr: SocketAddr) -> Handle<eyre::Result<()>> {
19    context.spawn(move |context| async move {
20        // Create a tokio listener for the metrics server.
21        //
22        // We explicitly avoid using a runtime `Listener` because
23        // it will track bandwidth used for metrics and apply a policy
24        // for read/write timeouts fit for a p2p network.
25        let listener = TcpListener::bind(listen_addr)
26            .await
27            .wrap_err("failed to bind provided address")?;
28
29        // Create a router for the metrics server
30        let app = Router::new()
31            .route(
32                "/metrics",
33                get(|Extension(ctx): Extension<Context>| async move {
34                    Response::builder()
35                        .status(StatusCode::OK)
36                        .header(header::CONTENT_TYPE, "text/plain; version=0.0.4")
37                        .body(Body::from(ctx.encode()))
38                        .expect("Failed to create response")
39                }),
40            )
41            .layer(Extension(context));
42
43        // Serve the metrics over HTTP.
44        //
45        // `serve` will spawn its own tasks using `tokio::spawn` (and there is no way to specify
46        // it to do otherwise). These tasks will not be tracked like metrics spawned using `Spawner`.
47        axum::serve(listener, app.into_make_service())
48            .await
49            .map_err(Into::into)
50    })
51}