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

Initial metrics integration #37

Merged
merged 25 commits into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
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
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# Subcoin: Bitcoin Full Node in Substrate
<div align="center">

<p align="center"><img width="400" src="./docs/images/subcoin-high-resolution-logo.png" alt="Subcoin logo"></p>

[![Continuous integration](https://github.com/subcoin-project/subcoin/actions/workflows/ci.yml/badge.svg)](https://github.com/subcoin-project/subcoin/actions/workflows/ci.yml)
[![Docs](https://github.com/subcoin-project/subcoin/actions/workflows/docs.yml/badge.svg)](https://github.com/subcoin-project/subcoin/actions/workflows/docs.yml)
[![Static Badge](https://img.shields.io/badge/User%20Guide-blue?logo=mdBook&logoColor=%23292b2e&link=https%3A%2F%2Fsubcoin-project.github.io%2Fsubcoin%2Fbook)](https://subcoin-project.github.io/subcoin/book)

</div>

> [!WARNING]
>
> Subcoin is currently in its early development stages and is not yet ready for production use.
Expand Down
1 change: 1 addition & 0 deletions crates/sc-consensus-nakamoto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ sp-io = { workspace = true }
sp-runtime = { workspace = true }
sp-state-machine = { workspace = true }
subcoin-primitives = { workspace = true }
substrate-prometheus-endpoint = { workspace = true }
thiserror = { workspace = true }
tracing = { workspace = true }

Expand Down
52 changes: 49 additions & 3 deletions crates/sc-consensus-nakamoto/src/block_import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
//! An enum representing the result of an import operation, with variants for different import outcomes.

use crate::block_executor::{BlockExecutor, ExecuteBlockResult};
use crate::metrics::Metrics;
use crate::verification::{BlockVerification, BlockVerifier};
use bitcoin::hashes::Hash;
use bitcoin::{Block as BitcoinBlock, BlockHash, Network};
Expand All @@ -37,10 +38,12 @@ use sp_runtime::traits::{
use sp_runtime::{SaturatedConversion, Saturating};
use std::marker::PhantomData;
use std::sync::Arc;
use std::time::Instant;
use subcoin_primitives::runtime::Subcoin;
use subcoin_primitives::{
substrate_header_digest, BackendExt, BitcoinTransactionAdapter, CoinStorageKey,
};
use substrate_prometheus_endpoint::Registry;

pub(crate) fn clone_storage_changes<Block: BlockT>(
c: &sp_state_machine::StorageChanges<HashingFor<Block>>,
Expand Down Expand Up @@ -129,6 +132,8 @@ pub struct BitcoinBlockImporter<Block, Client, BE, BI, TransactionAdapter> {
config: ImportConfig,
verifier: BlockVerifier<Block, Client, BE>,
block_executor: Box<dyn BlockExecutor<Block>>,
metrics: Option<Metrics>,
last_block_execution_report: Instant,
_phantom: PhantomData<TransactionAdapter>,
}

Expand Down Expand Up @@ -156,6 +161,7 @@ where
config: ImportConfig,
coin_storage_key: Arc<dyn CoinStorageKey>,
block_executor: Box<dyn BlockExecutor<Block>>,
registry: Option<&Registry>,
) -> Self {
let verifier = BlockVerifier::new(
client.clone(),
Expand All @@ -164,13 +170,23 @@ where
coin_storage_key,
config.verify_script,
);
let metrics = match registry {
Some(registry) => Metrics::register(registry)
.map_err(|err| {
tracing::error!("Failed to registry metrics: {err:?}");
})
.ok(),
None => None,
};
Self {
client,
inner: block_import,
stats: Stats::default(),
config,
verifier,
block_executor,
metrics,
last_block_execution_report: Instant::now(),
_phantom: Default::default(),
}
}
Expand Down Expand Up @@ -209,19 +225,46 @@ where
}

fn execute_block_at(
&self,
&mut self,
block_number: NumberFor<Block>,
parent_hash: Block::Hash,
block: Block,
) -> sp_blockchain::Result<(
Block::Hash,
sp_state_machine::StorageChanges<HashingFor<Block>>,
)> {
let timer = std::time::Instant::now();

let transactions_count = block.extrinsics().len();
let block_size = block.encoded_size();

let ExecuteBlockResult {
state_root,
storage_changes,
exec_info: _,
} = self.block_executor.execute_block(parent_hash, block)?;

if let Some(metrics) = &self.metrics {
const BLOCK_EXECUTION_REPORT_INTERVAL: u128 = 50;

// Executing blocks before 200000 is pretty fast, it becomes
// increasingly slower beyond this point, we only cares about
// the slow block executions.
if self.last_block_execution_report.elapsed().as_millis()
> BLOCK_EXECUTION_REPORT_INTERVAL
{
let block_number: u32 = block_number.saturated_into();
let execution_time = timer.elapsed().as_millis();
metrics.report_block_execution(
block_number.saturated_into(),
transactions_count,
block_size,
execution_time,
);
self.last_block_execution_report = Instant::now();
}
}

Ok((state_root, storage_changes))
}

Expand Down Expand Up @@ -266,8 +309,11 @@ where

let tx_count = extrinsics.len();

let (state_root, storage_changes) =
self.execute_block_at(parent_hash, Block::new(header.clone(), extrinsics.clone()))?;
let (state_root, storage_changes) = self.execute_block_at(
block_number,
parent_hash,
Block::new(header.clone(), extrinsics.clone()),
)?;

let execution_time = now.elapsed().as_millis();

Expand Down
1 change: 1 addition & 0 deletions crates/sc-consensus-nakamoto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod block_executor;
mod block_import;
mod chain_params;
mod import_queue;
mod metrics;
mod verification;

pub use block_executor::{
Expand Down
60 changes: 60 additions & 0 deletions crates/sc-consensus-nakamoto/src/metrics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use substrate_prometheus_endpoint::{register, GaugeVec, Opts, PrometheusError, Registry, U64};

pub struct Metrics {
block_execution_time: GaugeVec<U64>,
block_transactions_count: GaugeVec<U64>,
block_size: GaugeVec<U64>,
}

impl Metrics {
pub fn register(registry: &Registry) -> Result<Self, PrometheusError> {
Ok(Self {
block_execution_time: register(
GaugeVec::new(
Opts::new(
"subcoin_block_execution_time_milliseconds",
"Time taken to execute a block in milliseconds",
),
&["block_height"],
)?,
registry,
)?,
block_transactions_count: register(
GaugeVec::new(
Opts::new(
"subcoin_block_transactions_count",
"Number of transactions in the block",
),
&["block_height"],
)?,
registry,
)?,
block_size: register(
GaugeVec::new(
Opts::new("subcoin_block_size", "Block size in bytes"),
&["block_height"],
)?,
registry,
)?,
})
}

pub fn report_block_execution(
&self,
block_height: u32,
transactions_count: usize,
block_size: usize,
execution_time: u128,
) {
let block_height = block_height.to_string();
self.block_transactions_count
.with_label_values(&[&block_height])
.set(transactions_count as u64);
self.block_size
.with_label_values(&[&block_height])
.set(block_size as u64);
self.block_execution_time
.with_label_values(&[&block_height])
.set(execution_time as u64);
}
}
1 change: 1 addition & 0 deletions crates/subcoin-network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ sp-consensus = { workspace = true }
sp-core = { workspace = true }
sp-runtime = { workspace = true }
subcoin-primitives = { workspace = true }
substrate-prometheus-endpoint = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["full"] }
tracing = { workspace = true }
Expand Down
4 changes: 4 additions & 0 deletions crates/subcoin-network/src/address_book.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ impl AddressBook {
self.discovered_addresses.len() >= self.max_addresses
}

pub fn available_addresses_count(&self) -> usize {
self.discovered_addresses.len()
}

/// Pops a random address from the discovered addresses and marks it as active.
pub fn pop(&mut self) -> Option<PeerId> {
let maybe_peer = self.rng.choice(self.discovered_addresses.clone());
Expand Down
Loading