Skip to content

Commit

Permalink
refactor(hermes): state->wormhole/metrics downcasting (#1535)
Browse files Browse the repository at this point in the history
* refactor(hermes): state->wormhole/metrics downcasting
* fix(hermes): work around clippy auto-fix bug
  • Loading branch information
Reisen authored May 14, 2024
1 parent 9854a5d commit b6f5bf1
Show file tree
Hide file tree
Showing 12 changed files with 454 additions and 309 deletions.
4 changes: 2 additions & 2 deletions apps/hermes/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ mod ws;
pub struct ApiState<S = State> {
pub state: Arc<S>,
pub ws: Arc<ws::WsState>,
pub metrics: Arc<metrics_middleware::Metrics>,
pub metrics: Arc<metrics_middleware::ApiMetrics>,
}

/// Manually implement `Clone` as the derive macro will try and slap `Clone` on
Expand All @@ -49,7 +49,7 @@ impl ApiState<State> {
requester_ip_header_name: String,
) -> Self {
Self {
metrics: Arc::new(metrics_middleware::Metrics::new(state.clone())),
metrics: Arc::new(metrics_middleware::ApiMetrics::new(state.clone())),
ws: Arc::new(ws::WsState::new(
ws_whitelist,
requester_ip_header_name,
Expand Down
41 changes: 25 additions & 16 deletions apps/hermes/src/api/metrics_middleware.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use {
super::ApiState,
crate::state::State as AppState,
crate::state::metrics::Metrics,
axum::{
extract::{
MatchedPath,
Expand All @@ -22,13 +22,19 @@ use {
tokio::time::Instant,
};

pub struct Metrics {
pub struct ApiMetrics {
pub requests: Family<Labels, Counter>,
pub latencies: Family<Labels, Histogram>,
}

impl Metrics {
pub fn new(state: Arc<AppState>) -> Self {
impl ApiMetrics {
pub fn new<S>(state: Arc<S>) -> Self
where
S: Metrics,
S: Send,
S: Sync,
S: 'static,
{
let new = Self {
requests: Family::default(),
latencies: Family::new_with_constructor(|| {
Expand All @@ -46,15 +52,21 @@ impl Metrics {
let latencies = new.latencies.clone();

tokio::spawn(async move {
let mut metrics_registry = state.metrics_registry.write().await;

metrics_registry.register("api_requests", "Total number of API requests", requests);
Metrics::register(
&*state,
("api_requests", "Total number of API requests", requests),
)
.await;

metrics_registry.register(
"api_request_latency_seconds",
"API request latency in seconds",
latencies,
);
Metrics::register(
&*state,
(
"api_request_latency_seconds",
"API request latency in seconds",
latencies,
),
)
.await;
});
}

Expand All @@ -80,21 +92,18 @@ pub async fn track_metrics<B>(
} else {
req.uri().path().to_owned()
};
let method = req.method().clone();

let method = req.method().clone();
let response = next.run(req).await;

let latency = start.elapsed().as_secs_f64();
let status = response.status().as_u16();

let labels = Labels {
method: method.to_string(),
path,
status,
};

api_state.metrics.requests.get_or_create(&labels).inc();

api_state
.metrics
.latencies
Expand Down
2 changes: 1 addition & 1 deletion apps/hermes/src/api/rest/v2/sse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ where
{
Ok(Some(update)) => Ok(Event::default()
.json_data(update)
.unwrap_or_else(|e| error_event(e))),
.unwrap_or_else(error_event)),
Ok(None) => Ok(Event::default().comment("No update available")),
Err(e) => Ok(error_event(e)),
}
Expand Down
33 changes: 22 additions & 11 deletions apps/hermes/src/api/ws.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use {
AggregationEvent,
RequestTime,
},
metrics::Metrics,
State,
},
anyhow::{
Expand Down Expand Up @@ -115,12 +116,18 @@ pub struct Labels {
pub status: Status,
}

pub struct Metrics {
pub struct WsMetrics {
pub interactions: Family<Labels, Counter>,
}

impl Metrics {
pub fn new(state: Arc<State>) -> Self {
impl WsMetrics {
pub fn new<S>(state: Arc<S>) -> Self
where
S: Metrics,
S: Send,
S: Sync,
S: 'static,
{
let new = Self {
interactions: Family::default(),
};
Expand All @@ -129,11 +136,15 @@ impl Metrics {
let interactions = new.interactions.clone();

tokio::spawn(async move {
state.metrics_registry.write().await.register(
"ws_interactions",
"Total number of websocket interactions",
interactions,
);
Metrics::register(
&*state,
(
"ws_interactions",
"Total number of websocket interactions",
interactions,
),
)
.await;
});
}

Expand All @@ -146,7 +157,7 @@ pub struct WsState {
pub bytes_limit_whitelist: Vec<IpNet>,
pub rate_limiter: DefaultKeyedRateLimiter<IpAddr>,
pub requester_ip_header_name: String,
pub metrics: Metrics,
pub metrics: WsMetrics,
}

impl WsState {
Expand All @@ -158,7 +169,7 @@ impl WsState {
))),
bytes_limit_whitelist: whitelist,
requester_ip_header_name,
metrics: Metrics::new(state.clone()),
metrics: WsMetrics::new(state.clone()),
}
}
}
Expand Down Expand Up @@ -344,7 +355,7 @@ where
_ = self.exit.changed() => {
self.sender.close().await?;
self.closed = true;
return Err(anyhow!("Application is shutting down. Closing connection."));
Err(anyhow!("Application is shutting down. Closing connection."))
}
}
}
Expand Down
14 changes: 5 additions & 9 deletions apps/hermes/src/metrics_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
use {
crate::{
config::RunOptions,
state::State as AppState,
state::{
metrics::Metrics,
State as AppState,
},
},
anyhow::Result,
axum::{
Expand All @@ -15,7 +18,6 @@ use {
routing::get,
Router,
},
prometheus_client::encoding::text::encode,
std::sync::Arc,
};

Expand Down Expand Up @@ -43,13 +45,7 @@ pub async fn run(opts: RunOptions, state: Arc<AppState>) -> Result<()> {
}

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, &registry).unwrap();

let buffer = Metrics::encode(&*state).await;
(
[(
header::CONTENT_TYPE,
Expand Down
15 changes: 9 additions & 6 deletions apps/hermes/src/network/pythnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use {
api::types::PriceFeedMetadata,
config::RunOptions,
network::wormhole::{
update_guardian_set,
BridgeData,
GuardianSet,
GuardianSetData,
Expand All @@ -22,6 +21,7 @@ use {
Aggregates,
Update,
},
wormhole::Wormhole,
State,
},
},
Expand Down Expand Up @@ -215,11 +215,14 @@ pub async fn run(store: Arc<State>, pythnet_ws_endpoint: String) -> Result<!> {
/// This method performs the necessary work to pull down the bridge state and associated guardian
/// sets from a deployed Wormhole contract. Note that we only fetch the last two accounts due to
/// the fact that during a Wormhole upgrade, there will only be messages produces from those two.
async fn fetch_existing_guardian_sets(
state: Arc<State>,
async fn fetch_existing_guardian_sets<S>(
state: Arc<S>,
pythnet_http_endpoint: String,
wormhole_contract_addr: Pubkey,
) -> Result<()> {
) -> Result<()>
where
S: Wormhole,
{
let client = RpcClient::new(pythnet_http_endpoint.to_string());
let bridge = fetch_bridge_data(&client, &wormhole_contract_addr).await?;

Expand All @@ -233,7 +236,7 @@ async fn fetch_existing_guardian_sets(
"Retrieved Current GuardianSet.",
);

update_guardian_set(&state, bridge.guardian_set_index, current).await;
Wormhole::update_guardian_set(&*state, bridge.guardian_set_index, current).await;

// If there are more than one guardian set, we want to fetch the previous one as well as it
// may still be in transition phase if a guardian upgrade has just occurred.
Expand All @@ -251,7 +254,7 @@ async fn fetch_existing_guardian_sets(
"Retrieved Previous GuardianSet.",
);

update_guardian_set(&state, bridge.guardian_set_index - 1, previous).await;
Wormhole::update_guardian_set(&*state, bridge.guardian_set_index - 1, previous).await;
}

Ok(())
Expand Down
Loading

0 comments on commit b6f5bf1

Please sign in to comment.