mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(metrics): split DownloaderMetrics into body and headers downloaders (#3171)
This commit is contained in:
@ -1,5 +1,5 @@
|
|||||||
use super::queue::BodiesRequestQueue;
|
use super::queue::BodiesRequestQueue;
|
||||||
use crate::{bodies::task::TaskDownloader, metrics::DownloaderMetrics};
|
use crate::{bodies::task::TaskDownloader, metrics::BodyDownloaderMetrics};
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use reth_db::{cursor::DbCursorRO, database::Database, tables, transaction::DbTx};
|
use reth_db::{cursor::DbCursorRO, database::Database, tables, transaction::DbTx};
|
||||||
@ -63,7 +63,7 @@ pub struct BodiesDownloader<B: BodiesClient, DB> {
|
|||||||
/// Queued body responses that can be returned for insertion into the database.
|
/// Queued body responses that can be returned for insertion into the database.
|
||||||
queued_bodies: Vec<BlockResponse>,
|
queued_bodies: Vec<BlockResponse>,
|
||||||
/// The bodies downloader metrics.
|
/// The bodies downloader metrics.
|
||||||
metrics: DownloaderMetrics,
|
metrics: BodyDownloaderMetrics,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B, DB> BodiesDownloader<B, DB>
|
impl<B, DB> BodiesDownloader<B, DB>
|
||||||
@ -559,7 +559,7 @@ impl BodiesDownloaderBuilder {
|
|||||||
concurrent_requests_range,
|
concurrent_requests_range,
|
||||||
max_buffered_blocks: max_buffered_responses,
|
max_buffered_blocks: max_buffered_responses,
|
||||||
} = self;
|
} = self;
|
||||||
let metrics = DownloaderMetrics::new(BODIES_DOWNLOADER_SCOPE);
|
let metrics = BodyDownloaderMetrics::default();
|
||||||
let in_progress_queue = BodiesRequestQueue::new(metrics.clone());
|
let in_progress_queue = BodiesRequestQueue::new(metrics.clone());
|
||||||
BodiesDownloader {
|
BodiesDownloader {
|
||||||
client: Arc::new(client),
|
client: Arc::new(client),
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use super::request::BodiesRequestFuture;
|
use super::request::BodiesRequestFuture;
|
||||||
use crate::metrics::DownloaderMetrics;
|
use crate::metrics::BodyDownloaderMetrics;
|
||||||
use futures::{stream::FuturesUnordered, Stream};
|
use futures::{stream::FuturesUnordered, Stream};
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
use reth_interfaces::{
|
use reth_interfaces::{
|
||||||
@ -23,7 +23,7 @@ pub(crate) struct BodiesRequestQueue<B: BodiesClient> {
|
|||||||
/// Inner body request queue.
|
/// Inner body request queue.
|
||||||
inner: FuturesUnordered<BodiesRequestFuture<B>>,
|
inner: FuturesUnordered<BodiesRequestFuture<B>>,
|
||||||
/// The downloader metrics.
|
/// The downloader metrics.
|
||||||
metrics: DownloaderMetrics,
|
metrics: BodyDownloaderMetrics,
|
||||||
/// Last requested block number.
|
/// Last requested block number.
|
||||||
pub(crate) last_requested_block_number: Option<BlockNumber>,
|
pub(crate) last_requested_block_number: Option<BlockNumber>,
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ where
|
|||||||
B: BodiesClient + 'static,
|
B: BodiesClient + 'static,
|
||||||
{
|
{
|
||||||
/// Create new instance of request queue.
|
/// Create new instance of request queue.
|
||||||
pub(crate) fn new(metrics: DownloaderMetrics) -> Self {
|
pub(crate) fn new(metrics: BodyDownloaderMetrics) -> Self {
|
||||||
Self { metrics, inner: Default::default(), last_requested_block_number: None }
|
Self { metrics, inner: Default::default(), last_requested_block_number: None }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::metrics::DownloaderMetrics;
|
use crate::metrics::BodyDownloaderMetrics;
|
||||||
use futures::{Future, FutureExt};
|
use futures::{Future, FutureExt};
|
||||||
use reth_interfaces::{
|
use reth_interfaces::{
|
||||||
consensus::{Consensus as ConsensusTrait, Consensus},
|
consensus::{Consensus as ConsensusTrait, Consensus},
|
||||||
@ -38,7 +38,7 @@ use std::{
|
|||||||
pub(crate) struct BodiesRequestFuture<B: BodiesClient> {
|
pub(crate) struct BodiesRequestFuture<B: BodiesClient> {
|
||||||
client: Arc<B>,
|
client: Arc<B>,
|
||||||
consensus: Arc<dyn Consensus>,
|
consensus: Arc<dyn Consensus>,
|
||||||
metrics: DownloaderMetrics,
|
metrics: BodyDownloaderMetrics,
|
||||||
// Headers to download. The collection is shrunk as responses are buffered.
|
// Headers to download. The collection is shrunk as responses are buffered.
|
||||||
pending_headers: VecDeque<SealedHeader>,
|
pending_headers: VecDeque<SealedHeader>,
|
||||||
/// Internal buffer for all blocks
|
/// Internal buffer for all blocks
|
||||||
@ -56,7 +56,7 @@ where
|
|||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
client: Arc<B>,
|
client: Arc<B>,
|
||||||
consensus: Arc<dyn Consensus>,
|
consensus: Arc<dyn Consensus>,
|
||||||
metrics: DownloaderMetrics,
|
metrics: BodyDownloaderMetrics,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
client,
|
client,
|
||||||
@ -235,7 +235,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
bodies::test_utils::zip_blocks,
|
bodies::test_utils::zip_blocks,
|
||||||
test_utils::{generate_bodies, TestBodiesClient, TEST_SCOPE},
|
test_utils::{generate_bodies, TestBodiesClient},
|
||||||
};
|
};
|
||||||
use reth_interfaces::{
|
use reth_interfaces::{
|
||||||
p2p::bodies::response::BlockResponse,
|
p2p::bodies::response::BlockResponse,
|
||||||
@ -253,7 +253,7 @@ mod tests {
|
|||||||
let fut = BodiesRequestFuture::new(
|
let fut = BodiesRequestFuture::new(
|
||||||
client.clone(),
|
client.clone(),
|
||||||
Arc::new(TestConsensus::default()),
|
Arc::new(TestConsensus::default()),
|
||||||
DownloaderMetrics::new(TEST_SCOPE),
|
BodyDownloaderMetrics::default(),
|
||||||
)
|
)
|
||||||
.with_headers(headers.clone());
|
.with_headers(headers.clone());
|
||||||
|
|
||||||
@ -277,7 +277,7 @@ mod tests {
|
|||||||
let fut = BodiesRequestFuture::new(
|
let fut = BodiesRequestFuture::new(
|
||||||
client.clone(),
|
client.clone(),
|
||||||
Arc::new(TestConsensus::default()),
|
Arc::new(TestConsensus::default()),
|
||||||
DownloaderMetrics::new(TEST_SCOPE),
|
BodyDownloaderMetrics::default(),
|
||||||
)
|
)
|
||||||
.with_headers(headers.clone());
|
.with_headers(headers.clone());
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
//! A headers downloader that can handle multiple requests concurrently.
|
//! A headers downloader that can handle multiple requests concurrently.
|
||||||
|
|
||||||
use super::task::TaskDownloader;
|
use super::task::TaskDownloader;
|
||||||
use crate::metrics::DownloaderMetrics;
|
use crate::metrics::HeaderDownloaderMetrics;
|
||||||
use futures::{stream::Stream, FutureExt};
|
use futures::{stream::Stream, FutureExt};
|
||||||
use futures_util::{stream::FuturesUnordered, StreamExt};
|
use futures_util::{stream::FuturesUnordered, StreamExt};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
@ -37,9 +37,6 @@ use tracing::{error, trace};
|
|||||||
/// downloader is yielding a next batch of headers that is being committed to the database.
|
/// downloader is yielding a next batch of headers that is being committed to the database.
|
||||||
const REQUESTS_PER_PEER_MULTIPLIER: usize = 5;
|
const REQUESTS_PER_PEER_MULTIPLIER: usize = 5;
|
||||||
|
|
||||||
/// The scope for headers downloader metrics.
|
|
||||||
pub const HEADERS_DOWNLOADER_SCOPE: &str = "downloaders.headers";
|
|
||||||
|
|
||||||
/// Wrapper for internal downloader errors.
|
/// Wrapper for internal downloader errors.
|
||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
@ -100,7 +97,7 @@ pub struct ReverseHeadersDownloader<H: HeadersClient> {
|
|||||||
/// Note: headers are sorted from high to low
|
/// Note: headers are sorted from high to low
|
||||||
queued_validated_headers: Vec<SealedHeader>,
|
queued_validated_headers: Vec<SealedHeader>,
|
||||||
/// Header downloader metrics.
|
/// Header downloader metrics.
|
||||||
metrics: DownloaderMetrics,
|
metrics: HeaderDownloaderMetrics,
|
||||||
}
|
}
|
||||||
|
|
||||||
// === impl ReverseHeadersDownloader ===
|
// === impl ReverseHeadersDownloader ===
|
||||||
@ -1163,7 +1160,7 @@ impl ReverseHeadersDownloaderBuilder {
|
|||||||
in_progress_queue: Default::default(),
|
in_progress_queue: Default::default(),
|
||||||
buffered_responses: Default::default(),
|
buffered_responses: Default::default(),
|
||||||
queued_validated_headers: Default::default(),
|
queued_validated_headers: Default::default(),
|
||||||
metrics: DownloaderMetrics::new(HEADERS_DOWNLOADER_SCOPE),
|
metrics: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,22 +4,21 @@ use reth_metrics::{
|
|||||||
Metrics,
|
Metrics,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Common downloader metrics.
|
/// Common body downloader metrics.
|
||||||
///
|
///
|
||||||
/// These metrics will be dynamically initialized with the provided scope
|
/// These metrics will be initialized with the `downloaders.bodies` scope.
|
||||||
/// by corresponding downloaders.
|
|
||||||
/// ```
|
/// ```
|
||||||
/// use reth_downloaders::metrics::DownloaderMetrics;
|
/// use reth_downloaders::metrics::BodyDownloaderMetrics;
|
||||||
/// use reth_interfaces::p2p::error::DownloadError;
|
/// use reth_interfaces::p2p::error::DownloadError;
|
||||||
///
|
///
|
||||||
/// // Initialize metrics.
|
/// // Initialize metrics.
|
||||||
/// let metrics = DownloaderMetrics::new("downloaders.headers");
|
/// let metrics = BodyDownloaderMetrics::default();
|
||||||
/// // Increment `downloaders.headers.timeout_errors` counter by 1.
|
/// // Increment `downloaders.bodies.timeout_errors` counter by 1.
|
||||||
/// metrics.increment_errors(&DownloadError::Timeout);
|
/// metrics.increment_errors(&DownloadError::Timeout);
|
||||||
/// ```
|
/// ```
|
||||||
#[derive(Clone, Metrics)]
|
#[derive(Clone, Metrics)]
|
||||||
#[metrics(dynamic = true)]
|
#[metrics(scope = "downloaders.bodies")]
|
||||||
pub struct DownloaderMetrics {
|
pub struct BodyDownloaderMetrics {
|
||||||
/// The number of items that were successfully sent to the poller (stage)
|
/// The number of items that were successfully sent to the poller (stage)
|
||||||
pub total_flushed: Counter,
|
pub total_flushed: Counter,
|
||||||
/// Number of items that were successfully downloaded
|
/// Number of items that were successfully downloaded
|
||||||
@ -39,13 +38,10 @@ pub struct DownloaderMetrics {
|
|||||||
/// The number blocks that are contiguous and are queued for insertion into the db.
|
/// The number blocks that are contiguous and are queued for insertion into the db.
|
||||||
pub queued_blocks: Gauge,
|
pub queued_blocks: Gauge,
|
||||||
/// The number of out-of-order requests sent by the downloader.
|
/// The number of out-of-order requests sent by the downloader.
|
||||||
/// The consumer of the download stream is able to re-request data (headers or bodies) in case
|
/// The consumer of the download stream is able to re-request data (bodies) in case
|
||||||
/// it encountered a recoverable error (e.g. during insertion).
|
/// it encountered a recoverable error (e.g. during insertion).
|
||||||
/// Out-of-order request happen when:
|
/// Out-of-order request happen when the new download range start for bodies downloader
|
||||||
/// - the headers downloader `SyncTarget::Tip` hash is different from the previous sync
|
/// is less than the last block number returned from the stream.
|
||||||
/// target hash.
|
|
||||||
/// - the new download range start for bodies donwloader is less than the last block number
|
|
||||||
/// returned from the stream.
|
|
||||||
pub out_of_order_requests: Counter,
|
pub out_of_order_requests: Counter,
|
||||||
/// Number of timeout errors while requesting items
|
/// Number of timeout errors while requesting items
|
||||||
pub timeout_errors: Counter,
|
pub timeout_errors: Counter,
|
||||||
@ -55,14 +51,70 @@ pub struct DownloaderMetrics {
|
|||||||
pub unexpected_errors: Counter,
|
pub unexpected_errors: Counter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DownloaderMetrics {
|
impl BodyDownloaderMetrics {
|
||||||
/// Increment errors counter.
|
/// Increment errors counter.
|
||||||
pub fn increment_errors(&self, error: &DownloadError) {
|
pub fn increment_errors(&self, error: &DownloadError) {
|
||||||
match error {
|
match error {
|
||||||
DownloadError::Timeout => self.timeout_errors.increment(1),
|
DownloadError::Timeout => self.timeout_errors.increment(1),
|
||||||
DownloadError::HeaderValidation { .. } | DownloadError::BodyValidation { .. } => {
|
DownloadError::BodyValidation { .. } => self.validation_errors.increment(1),
|
||||||
self.validation_errors.increment(1)
|
_error => self.unexpected_errors.increment(1),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Common header downloader metrics.
|
||||||
|
///
|
||||||
|
/// These metrics will be initialized with the `downloaders.headers` scope.
|
||||||
|
/// ```
|
||||||
|
/// use reth_downloaders::metrics::HeaderDownloaderMetrics;
|
||||||
|
/// use reth_interfaces::p2p::error::DownloadError;
|
||||||
|
///
|
||||||
|
/// // Initialize metrics.
|
||||||
|
/// let metrics = HeaderDownloaderMetrics::default();
|
||||||
|
/// // Increment `downloaders.headers.timeout_errors` counter by 1.
|
||||||
|
/// metrics.increment_errors(&DownloadError::Timeout);
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Metrics)]
|
||||||
|
#[metrics(scope = "downloaders.headers")]
|
||||||
|
pub struct HeaderDownloaderMetrics {
|
||||||
|
/// The number of items that were successfully sent to the poller (stage)
|
||||||
|
pub total_flushed: Counter,
|
||||||
|
/// Number of items that were successfully downloaded
|
||||||
|
pub total_downloaded: Counter,
|
||||||
|
/// The number of requests (can contain more than 1 item) currently in-flight.
|
||||||
|
pub in_flight_requests: Gauge,
|
||||||
|
/// The number of responses (can contain more than 1 item) in the internal buffer of the
|
||||||
|
/// downloader.
|
||||||
|
pub buffered_responses: Gauge,
|
||||||
|
/// The number of blocks the internal buffer of the
|
||||||
|
/// downloader.
|
||||||
|
/// These are bodies that have been received, but not cannot be committed yet because they're
|
||||||
|
/// not contiguous
|
||||||
|
pub buffered_blocks: Gauge,
|
||||||
|
/// Total amount of memory used by the buffered blocks in bytes
|
||||||
|
pub buffered_blocks_size_bytes: Gauge,
|
||||||
|
/// The number blocks that are contiguous and are queued for insertion into the db.
|
||||||
|
pub queued_blocks: Gauge,
|
||||||
|
/// The number of out-of-order requests sent by the downloader.
|
||||||
|
/// The consumer of the download stream is able to re-request data (headers) in case
|
||||||
|
/// it encountered a recoverable error (e.g. during insertion).
|
||||||
|
/// Out-of-order request happen when the headers downloader `SyncTarget::Tip`
|
||||||
|
/// hash is different from the previous sync target hash.
|
||||||
|
pub out_of_order_requests: Counter,
|
||||||
|
/// Number of timeout errors while requesting items
|
||||||
|
pub timeout_errors: Counter,
|
||||||
|
/// Number of validation errors while requesting items
|
||||||
|
pub validation_errors: Counter,
|
||||||
|
/// Number of unexpected errors while requesting items
|
||||||
|
pub unexpected_errors: Counter,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HeaderDownloaderMetrics {
|
||||||
|
/// Increment errors counter.
|
||||||
|
pub fn increment_errors(&self, error: &DownloadError) {
|
||||||
|
match error {
|
||||||
|
DownloadError::Timeout => self.timeout_errors.increment(1),
|
||||||
|
DownloadError::HeaderValidation { .. } => self.validation_errors.increment(1),
|
||||||
_error => self.unexpected_errors.increment(1),
|
_error => self.unexpected_errors.increment(1),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user