refactor(hermes): move metrics endpoint to a separate metrics server
This commit is contained in:
parent
29dc1082dd
commit
8075d0704e
|
@ -1,6 +1,7 @@
|
||||||
export PYTHNET_HTTP_ADDR=http://pythnet-http-rpc/
|
export PYTHNET_HTTP_ADDR=http://pythnet-http-rpc/
|
||||||
export PYTHNET_WS_ADDR=ws://pythnet-ws-rpc/
|
export PYTHNET_WS_ADDR=ws://pythnet-ws-rpc/
|
||||||
export RPC_LISTEN_ADDR=0.0.0.0:7575
|
export RPC_LISTEN_ADDR=0.0.0.0:7575
|
||||||
|
export METRICS_LISTEN_ADDR=0.0.0.0:7576
|
||||||
export BENCHMARKS_ENDPOINT=https://benchmarks.pyth.network
|
export BENCHMARKS_ENDPOINT=https://benchmarks.pyth.network
|
||||||
export WORMHOLE_SPY_RPC_ADDR=http://spy-or-beacon-rpc
|
export WORMHOLE_SPY_RPC_ADDR=http://spy-or-beacon-rpc
|
||||||
export RUST_LOG=info
|
export RUST_LOG=info
|
||||||
|
|
|
@ -153,7 +153,6 @@ pub async fn run(opts: RunOptions, state: ApiState) -> Result<()> {
|
||||||
.route("/api/latest_vaas", get(rest::latest_vaas))
|
.route("/api/latest_vaas", get(rest::latest_vaas))
|
||||||
.route("/api/price_feed_ids", get(rest::price_feed_ids))
|
.route("/api/price_feed_ids", get(rest::price_feed_ids))
|
||||||
.route("/live", get(rest::live))
|
.route("/live", get(rest::live))
|
||||||
.route("/metrics", get(rest::metrics))
|
|
||||||
.route("/ready", get(rest::ready))
|
.route("/ready", get(rest::ready))
|
||||||
.route("/ws", get(ws::ws_route_handler))
|
.route("/ws", get(ws::ws_route_handler))
|
||||||
.route_layer(from_fn_with_state(
|
.route_layer(from_fn_with_state(
|
||||||
|
|
|
@ -17,7 +17,6 @@ mod index;
|
||||||
mod latest_price_feeds;
|
mod latest_price_feeds;
|
||||||
mod latest_vaas;
|
mod latest_vaas;
|
||||||
mod live;
|
mod live;
|
||||||
mod metrics;
|
|
||||||
mod price_feed_ids;
|
mod price_feed_ids;
|
||||||
mod ready;
|
mod ready;
|
||||||
|
|
||||||
|
@ -29,7 +28,6 @@ pub use {
|
||||||
latest_price_feeds::*,
|
latest_price_feeds::*,
|
||||||
latest_vaas::*,
|
latest_vaas::*,
|
||||||
live::*,
|
live::*,
|
||||||
metrics::*,
|
|
||||||
price_feed_ids::*,
|
price_feed_ids::*,
|
||||||
ready::*,
|
ready::*,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
//! Exposing prometheus metrics via HTTP in openmetrics format.
|
|
||||||
|
|
||||||
use {
|
|
||||||
axum::{
|
|
||||||
extract::State,
|
|
||||||
response::IntoResponse,
|
|
||||||
},
|
|
||||||
prometheus_client::encoding::text::encode,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub async fn metrics(State(state): State<crate::api::ApiState>) -> impl IntoResponse {
|
|
||||||
let registry = state.state.metrics_registry.read().await;
|
|
||||||
let mut buffer = String::new();
|
|
||||||
|
|
||||||
// Should not fail if the metrics are valid and there is memory available
|
|
||||||
// to write to the buffer.
|
|
||||||
encode(&mut buffer, ®istry).unwrap();
|
|
||||||
|
|
||||||
buffer
|
|
||||||
}
|
|
|
@ -8,6 +8,7 @@ use clap::{
|
||||||
};
|
};
|
||||||
|
|
||||||
mod benchmarks;
|
mod benchmarks;
|
||||||
|
mod metrics;
|
||||||
mod pythnet;
|
mod pythnet;
|
||||||
mod rpc;
|
mod rpc;
|
||||||
mod wormhole;
|
mod wormhole;
|
||||||
|
@ -44,6 +45,10 @@ pub struct RunOptions {
|
||||||
/// Benchmarks Options
|
/// Benchmarks Options
|
||||||
#[command(flatten)]
|
#[command(flatten)]
|
||||||
pub benchmarks: benchmarks::Options,
|
pub benchmarks: benchmarks::Options,
|
||||||
|
|
||||||
|
/// Metrics Options
|
||||||
|
#[command(flatten)]
|
||||||
|
pub metrics: metrics::Options,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Args, Clone, Debug)]
|
#[derive(Args, Clone, Debug)]
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
use {
|
||||||
|
clap::Args,
|
||||||
|
std::net::SocketAddr,
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_METRICS_SERVER_LISTEN_ADDR: &str = "127.0.0.1:33888";
|
||||||
|
|
||||||
|
#[derive(Args, Clone, Debug)]
|
||||||
|
#[command(next_help_heading = "Metrics Options")]
|
||||||
|
#[group(id = "Metrics")]
|
||||||
|
pub struct Options {
|
||||||
|
/// Address and port the RPC server will bind to.
|
||||||
|
#[arg(long = "metrics-server-listen-addr")]
|
||||||
|
#[arg(default_value = DEFAULT_METRICS_SERVER_LISTEN_ADDR)]
|
||||||
|
#[arg(env = "METRICS_LISTEN_ADDR")]
|
||||||
|
pub server_listen_addr: SocketAddr,
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ use {
|
||||||
mod aggregate;
|
mod aggregate;
|
||||||
mod api;
|
mod api;
|
||||||
mod config;
|
mod config;
|
||||||
|
mod metrics_server;
|
||||||
mod network;
|
mod network;
|
||||||
mod serde;
|
mod serde;
|
||||||
mod state;
|
mod state;
|
||||||
|
@ -61,6 +62,7 @@ async fn init() -> Result<()> {
|
||||||
let tasks = join_all([
|
let tasks = join_all([
|
||||||
Box::pin(spawn(network::wormhole::spawn(opts.clone(), store.clone()))),
|
Box::pin(spawn(network::wormhole::spawn(opts.clone(), store.clone()))),
|
||||||
Box::pin(spawn(network::pythnet::spawn(opts.clone(), store.clone()))),
|
Box::pin(spawn(network::pythnet::spawn(opts.clone(), store.clone()))),
|
||||||
|
Box::pin(spawn(metrics_server::run(opts.clone(), store.clone()))),
|
||||||
Box::pin(spawn(api::spawn(opts.clone(), store.clone(), update_rx))),
|
Box::pin(spawn(api::spawn(opts.clone(), store.clone(), update_rx))),
|
||||||
])
|
])
|
||||||
.await;
|
.await;
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
//! Metrics Server
|
||||||
|
//!
|
||||||
|
//! This server serves metrics over /metrics in OpenMetrics format.
|
||||||
|
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
config::RunOptions,
|
||||||
|
state::State as AppState,
|
||||||
|
},
|
||||||
|
anyhow::Result,
|
||||||
|
axum::{
|
||||||
|
extract::State,
|
||||||
|
response::IntoResponse,
|
||||||
|
routing::get,
|
||||||
|
Router,
|
||||||
|
},
|
||||||
|
prometheus_client::encoding::text::encode,
|
||||||
|
std::sync::{
|
||||||
|
atomic::Ordering,
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(opts, state))]
|
||||||
|
pub async fn run(opts: RunOptions, state: Arc<AppState>) -> Result<()> {
|
||||||
|
tracing::info!(endpoint = %opts.metrics.server_listen_addr, "Starting Metrics Server.");
|
||||||
|
|
||||||
|
let app = Router::new();
|
||||||
|
let app = app
|
||||||
|
.route("/metrics", get(metrics))
|
||||||
|
.with_state(state.clone());
|
||||||
|
|
||||||
|
// Binds the axum's server to the configured address and port. This is a blocking call and will
|
||||||
|
// not return until the server is shutdown.
|
||||||
|
axum::Server::try_bind(&opts.metrics.server_listen_addr)?
|
||||||
|
.serve(app.into_make_service())
|
||||||
|
.with_graceful_shutdown(async {
|
||||||
|
while !crate::SHOULD_EXIT.load(Ordering::Acquire) {
|
||||||
|
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracing::info!("Shutting down metrics server...");
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn metrics(State(state): State<Arc<AppState>>) -> impl IntoResponse {
|
||||||
|
let registry = state.metrics_registry.read().await;
|
||||||
|
let mut buffer = String::new();
|
||||||
|
|
||||||
|
// Should not fail if the metrics are valid and there is memory available
|
||||||
|
// to write to the buffer.
|
||||||
|
encode(&mut buffer, ®istry).unwrap();
|
||||||
|
|
||||||
|
buffer
|
||||||
|
}
|
Loading…
Reference in New Issue