commonware_runtime/telemetry/metrics/
server.rs

1//! Utilities to serve metrics over HTTP.
2
3use crate::{Listener, Metrics, Network, Sink, Stream};
4use std::net::SocketAddr;
5use tracing::{debug, error};
6
7/// Handles a single connection by sending back the current metrics.
8/// Ignores any data sent by the client.
9async fn encode<C, Si>(context: &C, mut sink: Si)
10where
11    C: Metrics,
12    Si: Sink,
13{
14    // Encode metrics from the provided context
15    let body = context.encode();
16
17    // Format a minimal HTTP 200 OK response
18    // Uses standard Prometheus content type and advises client to close
19    let response = format!(
20        "HTTP/1.1 200 OK\r\nContent-Type: text/plain; version=0.0.4\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",
21        body.len(),
22        body
23    );
24
25    // Send the response
26    if let Err(e) = sink.send(response.as_bytes()).await {
27        error!(error = ?e, "Failed to send metrics response");
28    }
29}
30
31/// Serve metrics over HTTP (on all methods and paths) for the given address.
32pub async fn serve<Si: Sink, St: Stream, L: Listener<Si, St>, C: Metrics + Network<L, Si, St>>(
33    context: C,
34    address: SocketAddr,
35) {
36    let mut listener = context
37        .bind(address)
38        .await
39        .expect("Could not bind to metrics address");
40    while let Ok((peer, sink, _)) = listener.accept().await {
41        debug!(?peer, "serving metrics");
42        encode(&context, sink).await;
43    }
44}