Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eth2Near-relay: add extra metrics to Prometheus #824

Merged
merged 2 commits into from
Sep 24, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions eth2near/eth2near-block-relay-rs/src/beacon_rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,11 +172,16 @@ impl BeaconRPCClient {
}

pub fn get_checkpoint_root(&self) -> Result<String, Box<dyn Error>> {
let url = format!("{}/eth/v1/beacon/states/finalized/finality_checkpoints", self.endpoint_url);
let url = format!(
"{}/eth/v1/beacon/states/finalized/finality_checkpoints",
self.endpoint_url
);
let checkpoint_json_str = self.get_json_from_raw_request(&url)?;
let parsed_json: Value = serde_json::from_str(&checkpoint_json_str)?;

Ok(trim_quotes(parsed_json["data"]["finalized"]["root"].to_string()))
Ok(trim_quotes(
parsed_json["data"]["finalized"]["root"].to_string(),
))
}

/// Return the last finalized slot in the Beacon chain
Expand Down
122 changes: 77 additions & 45 deletions eth2near/eth2near-block-relay-rs/src/eth2near_relay.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use std::cmp::max;
use crate::beacon_rpc_client::BeaconRPCClient;
use crate::config::Config;
use crate::eth1_rpc_client::Eth1RPCClient;
use crate::hand_made_finality_light_client_update::HandMadeFinalityLightClientUpdate;
use crate::last_slot_searcher::LastSlotSearcher;
use crate::near_rpc_client::NearRPCClient;
use crate::prometheus_metrics;
use crate::prometheus_metrics::{
FAILS_ON_HEADERS_SUBMISSION, FAILS_ON_UPDATES_SUBMISSION, LAST_ETH_SLOT, LAST_ETH_SLOT_ON_NEAR,
LAST_FINALIZED_ETH_SLOT, LAST_FINALIZED_ETH_SLOT_ON_NEAR,
};
use crate::prometheus_metrics::{CHAIN_EXECUTION_BLOCK_HEIGHT_ON_ETH, CHAIN_EXECUTION_BLOCK_HEIGHT_ON_NEAR, CHAIN_FINALIZED_EXECUTION_BLOCK_HEIGHT_ON_ETH, CHAIN_FINALIZED_EXECUTION_BLOCK_HEIGHT_ON_NEAR, FAILS_ON_HEADERS_SUBMISSION, FAILS_ON_UPDATES_SUBMISSION, LAST_ETH_SLOT, LAST_ETH_SLOT_ON_NEAR, LAST_FINALIZED_ETH_SLOT, LAST_FINALIZED_ETH_SLOT_ON_NEAR};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't import and just use in the code like prometheus_metrics::CHAIN_EXECUTION_BLOCK_HEIGHT_ON_ETH.
The crate is already imported.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, it is worth deferring it to the separate PR, so as to not bloat up the scope of the current one.

use crate::relay_errors::NoBlockForSlotError;
use contract_wrapper::eth_client_contract_trait::EthClientContractTrait;
use eth_types::eth2::LightClientUpdate;
Expand All @@ -20,6 +18,7 @@ use std::thread::sleep;
use std::thread::spawn;
use std::time::Duration;
use std::vec::Vec;
use types::Slot;

const ONE_EPOCH_IN_SLOTS: u64 = 32;

Expand Down Expand Up @@ -135,6 +134,62 @@ impl Eth2NearRelay {
eth2near_relay
}

fn get_max_slot_for_submission(&self) -> Result<u64, Box<dyn Error>> {
let last_eth2_slot = self.beacon_rpc_client.get_last_slot_number()?.as_u64();
LAST_ETH_SLOT.inc_by(max(0, last_eth2_slot as i64 - LAST_ETH_SLOT.get()));
info!(target: "relay", "Last slot on ETH = {}", last_eth2_slot);

let last_block_number = self.beacon_rpc_client.get_block_number_for_slot(Slot::new(last_eth2_slot))?;
CHAIN_EXECUTION_BLOCK_HEIGHT_ON_ETH.inc_by(max(0, last_block_number as i64 - CHAIN_EXECUTION_BLOCK_HEIGHT_ON_ETH.get()));

return if self.submit_only_finalized_blocks {
Ok(self.beacon_rpc_client.get_last_finalized_slot_number()?.as_u64())
} else {
Ok(last_eth2_slot)
}
}

fn get_last_eth2_slot_on_near(&mut self, max_slot: u64) -> Result<u64, Box<dyn Error>> {
let last_eth2_slot_on_near = self.last_slot_searcher.get_last_slot(
max_slot,
&self.beacon_rpc_client,
&self.eth_client_contract
)?;

LAST_ETH_SLOT_ON_NEAR
.inc_by(max(0,last_eth2_slot_on_near as i64 - LAST_ETH_SLOT_ON_NEAR.get()));

let last_block_number = self.beacon_rpc_client.get_block_number_for_slot(Slot::new(last_eth2_slot_on_near))?;
CHAIN_EXECUTION_BLOCK_HEIGHT_ON_NEAR.inc_by(max(0, last_block_number as i64 - CHAIN_EXECUTION_BLOCK_HEIGHT_ON_NEAR.get()));

return Ok(last_eth2_slot_on_near);
}

fn get_last_finalized_slot_on_near(&self) -> Result<u64, Box<dyn Error>> {
let last_finalized_slot_on_near = self.eth_client_contract.get_finalized_beacon_block_slot()?;
LAST_FINALIZED_ETH_SLOT_ON_NEAR
.inc_by(max(0, last_finalized_slot_on_near as i64 - LAST_FINALIZED_ETH_SLOT_ON_NEAR.get()));

let last_block_number = self.beacon_rpc_client.get_block_number_for_slot(Slot::new(last_finalized_slot_on_near))?;
CHAIN_FINALIZED_EXECUTION_BLOCK_HEIGHT_ON_NEAR.inc_by(max(0, last_block_number as i64 - CHAIN_FINALIZED_EXECUTION_BLOCK_HEIGHT_ON_NEAR.get()));

Ok(last_finalized_slot_on_near)
}

fn get_last_finalized_slot_on_eth(&self) -> Result<u64, Box<dyn Error>> {
let last_finalized_slot_on_eth = self
.beacon_rpc_client
.get_last_finalized_slot_number()?.as_u64();

LAST_FINALIZED_ETH_SLOT
.inc_by(max(0,last_finalized_slot_on_eth as i64 - LAST_FINALIZED_ETH_SLOT.get()));

let last_block_number = self.beacon_rpc_client.get_block_number_for_slot(Slot::new(last_finalized_slot_on_eth))?;
CHAIN_FINALIZED_EXECUTION_BLOCK_HEIGHT_ON_ETH.inc_by(max(0, last_block_number as i64 - CHAIN_FINALIZED_EXECUTION_BLOCK_HEIGHT_ON_ETH.get()));

Ok(last_finalized_slot_on_eth)
}

pub fn run(&mut self, max_iterations: Option<u64>) {
info!(target: "relay", "=== Relay running ===");
let mut iter_id = 0;
Expand All @@ -150,45 +205,27 @@ impl Eth2NearRelay {

info!(target: "relay", "== New relay loop ==");

let last_eth2_slot_on_eth_chain: u64 = if self.submit_only_finalized_blocks {
skip_fail!(
self.beacon_rpc_client.get_last_finalized_slot_number(),
"Fail to get last finalized slot on Eth",
self.sleep_time_on_sync_secs
)
.as_u64()
} else {
skip_fail!(
self.beacon_rpc_client.get_last_slot_number(),
"Fail to get last slot on Eth",
self.sleep_time_on_sync_secs
)
.as_u64()
};
let max_slot_for_submission: u64 = skip_fail!(
self.get_max_slot_for_submission(),
"Fail to get last slot on Eth",
self.sleep_time_on_sync_secs);

let mut last_eth2_slot_on_near: u64 = skip_fail!(
self.last_slot_searcher.get_last_slot(
last_eth2_slot_on_eth_chain,
&self.beacon_rpc_client,
&self.eth_client_contract
),
self.get_last_eth2_slot_on_near(max_slot_for_submission),
"Fail to get last slot on NEAR",
self.sleep_time_on_sync_secs
);

LAST_ETH_SLOT.inc_by(last_eth2_slot_on_eth_chain as i64 - LAST_ETH_SLOT.get());
LAST_ETH_SLOT_ON_NEAR
.inc_by(last_eth2_slot_on_near as i64 - LAST_ETH_SLOT_ON_NEAR.get());

info!(target: "relay", "Last slot on near = {}; last slot on eth = {}",
last_eth2_slot_on_near, last_eth2_slot_on_eth_chain);
info!(target: "relay", "Last slot on near = {}; max slot for submission = {}",
last_eth2_slot_on_near, max_slot_for_submission);

if last_eth2_slot_on_near < last_eth2_slot_on_eth_chain {
if last_eth2_slot_on_near < max_slot_for_submission {
info!(target: "relay", "= Creating headers batch =");

let (headers, current_slot) = skip_fail!(
self.get_execution_blocks_between(
last_eth2_slot_on_near + 1,
last_eth2_slot_on_eth_chain,
max_slot_for_submission,
),
"Network problems during fetching execution blocks",
self.sleep_time_on_sync_secs
Expand All @@ -198,20 +235,15 @@ impl Eth2NearRelay {
}

let last_finalized_slot_on_near: u64 = skip_fail!(
self.eth_client_contract.get_finalized_beacon_block_slot(),
"Error on getting finalized block hash. Skipping sending light client update",
self.get_last_finalized_slot_on_near(),
"Error on getting finalized block slot on NEAR. Skipping sending light client update",
self.sleep_time_on_sync_secs
);

let last_finalized_slot_on_eth: u64 = skip_fail!(
self.get_last_finalized_slot_on_eth(),
"Error on getting last finalized slot on Ethereum. Skipping sending light client update",
self.sleep_time_on_sync_secs);

let last_finalized_slot_on_eth: u64 = skip_fail!(self
.beacon_rpc_client
.get_last_finalized_slot_number(),
"Error on getting last finalized slot number on Ethereum. Skipping sending light client update",
self.sleep_time_on_sync_secs).as_u64();

LAST_FINALIZED_ETH_SLOT_ON_NEAR
.inc_by(last_finalized_slot_on_near as i64 - LAST_FINALIZED_ETH_SLOT_ON_NEAR.get());
LAST_FINALIZED_ETH_SLOT
.inc_by(last_finalized_slot_on_eth as i64 - LAST_FINALIZED_ETH_SLOT.get());

trace!(target: "relay", "last_finalized_slot on near/eth {}/{}", last_finalized_slot_on_near, last_finalized_slot_on_eth);

Expand Down
60 changes: 46 additions & 14 deletions eth2near/eth2near-block-relay-rs/src/prometheus_metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,54 +9,86 @@ use warp::Reply;
lazy_static! {
pub static ref REGISTRY: Registry = Registry::new();
pub static ref LAST_ETH_SLOT: IntCounter =
IntCounter::new("last_eth_slot", "Last Ethereum Slot").expect("metric can be created");
IntCounter::new("last_eth_slot", "Last Ethereum Slot").expect("metric can't be created");
pub static ref LAST_ETH_SLOT_ON_NEAR: IntCounter =
IntCounter::new("last_eth_slot_on_near", "Last Ethereum Slot on NEAR")
.expect("metric can be created");
.expect("metric can't be created");
pub static ref LAST_FINALIZED_ETH_SLOT: IntCounter =
IntCounter::new("last_finalized_eth_slot", "Last Finalized Ethereum Slot")
.expect("metric can be created");
.expect("metric can't be created");
pub static ref LAST_FINALIZED_ETH_SLOT_ON_NEAR: IntCounter = IntCounter::new(
"last_finalized_eth_slot_on_near",
"Last Finalized Ethereum Slot on NEAR"
)
.expect("metric can be created");
.expect("metric cann't be created");
sept-en marked this conversation as resolved.
Show resolved Hide resolved
pub static ref FAILS_ON_HEADERS_SUBMISSION: IntCounter = IntCounter::new(
"fails_on_headers_submission",
"Fails number on Headers Submission"
)
.expect("metric can be created");
.expect("metric cann't be created");
sept-en marked this conversation as resolved.
Show resolved Hide resolved
pub static ref FAILS_ON_UPDATES_SUBMISSION: IntCounter = IntCounter::new(
"fails_on_updates_submission",
"Fails number on Light Client Updates Submission"
)
.expect("metric can be created");
.expect("metric cann't be created");
sept-en marked this conversation as resolved.
Show resolved Hide resolved

pub static ref CHAIN_EXECUTION_BLOCK_HEIGHT_ON_ETH: IntCounter =
IntCounter::new("chain_execution_block_height_on_eth",
"Chain execution block height on eth").expect("metric cann't be created");
sept-en marked this conversation as resolved.
Show resolved Hide resolved

pub static ref CHAIN_FINALIZED_EXECUTION_BLOCK_HEIGHT_ON_ETH: IntCounter =
IntCounter::new("chain_finalized_execution_block_height_on_eth",
"Chain finalized execution block height on eth").expect("metric cann't be created");

pub static ref CHAIN_EXECUTION_BLOCK_HEIGHT_ON_NEAR: IntCounter =
IntCounter::new("chain_execution_block_height_on_near",
"Chain execution block height on near").expect("metric cann't be created");

pub static ref CHAIN_FINALIZED_EXECUTION_BLOCK_HEIGHT_ON_NEAR: IntCounter =
IntCounter::new("chain_finalized_execution_block_height_on_near",
"Chain finalized execution block height on near").expect("metric cann't be created");
sept-en marked this conversation as resolved.
Show resolved Hide resolved
}

fn register_custom_metrics() {
REGISTRY
.register(Box::new(LAST_ETH_SLOT.clone()))
.expect("collector can be registered");
.expect("last_eth_slot can't be registered");

REGISTRY
.register(Box::new(LAST_ETH_SLOT_ON_NEAR.clone()))
.expect("collector can be registered");
.expect("last_eth_slot_on_near can't be registered");

REGISTRY
.register(Box::new(LAST_FINALIZED_ETH_SLOT.clone()))
.expect("collector can be registered");
.expect("last_finalized_eth_slot can't be registered");

REGISTRY
.register(Box::new(LAST_FINALIZED_ETH_SLOT_ON_NEAR.clone()))
.expect("collector can be registered");
.expect("last_finalized_eth_slot_on_near can't be registered");

REGISTRY
.register(Box::new(FAILS_ON_HEADERS_SUBMISSION.clone()))
.expect("collector can be registered");
.expect("fails_on_header_submission can't be registered");

REGISTRY
.register(Box::new(FAILS_ON_UPDATES_SUBMISSION.clone()))
.expect("collector can be registered");
.expect("fails_on_updates_submission can't be registered");

REGISTRY
.register(Box::new(CHAIN_EXECUTION_BLOCK_HEIGHT_ON_ETH.clone()))
.expect("chain_execution_block_height_on_eth can't be registered");

REGISTRY
.register(Box::new(CHAIN_FINALIZED_EXECUTION_BLOCK_HEIGHT_ON_ETH.clone()))
.expect("chain_finalized_execution_block_height_on_eth can't be registered");

REGISTRY
.register(Box::new(CHAIN_EXECUTION_BLOCK_HEIGHT_ON_NEAR.clone()))
.expect("chain_execution_block_height_on_near can't be registered");

REGISTRY
.register(Box::new(CHAIN_FINALIZED_EXECUTION_BLOCK_HEIGHT_ON_NEAR.clone()))
.expect("chain_finalized_execution_block_height_on_near can't be registered");
}

async fn metrics_handler() -> Result<impl Reply, Rejection> {
Expand All @@ -65,7 +97,7 @@ async fn metrics_handler() -> Result<impl Reply, Rejection> {

let mut buffer = Vec::new();
if let Err(e) = encoder.encode(&REGISTRY.gather(), &mut buffer) {
eprintln!("could not encode custom metrics: {}", e);
eprintln!("could not encode custom metrics: {:?}", e);
};
let mut res = match String::from_utf8(buffer.clone()) {
Ok(v) => v,
Expand All @@ -77,7 +109,7 @@ async fn metrics_handler() -> Result<impl Reply, Rejection> {
buffer.clear();

if let Err(e) = encoder.encode(&prometheus::gather(), &mut buffer) {
eprintln!("could not encode prometheus metrics: {}", e);
eprintln!("could not encode prometheus metrics: {:?}", e);
};
let res_custom = match String::from_utf8(buffer.clone()) {
Ok(v) => v,
Expand Down