-
Notifications
You must be signed in to change notification settings - Fork 276
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[refactor]: Move metrics related functionality into MetricsReporter
Signed-off-by: Shanin Roman <[email protected]>
- Loading branch information
Showing
7 changed files
with
210 additions
and
167 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
//! Metrics and status reporting | ||
use std::sync::Arc; | ||
|
||
use eyre::{Result, WrapErr as _}; | ||
use iroha_data_model::current_time; | ||
use iroha_telemetry::metrics::Metrics; | ||
use parking_lot::Mutex; | ||
use storage::storage::StorageReadOnly; | ||
|
||
use crate::{ | ||
kura::Kura, | ||
queue::Queue, | ||
state::{State, StateReadOnly, WorldReadOnly}, | ||
IrohaNetwork, | ||
}; | ||
|
||
/* | ||
The values in the following struct are not atomics because the code that | ||
operates on them assumes their values does not change during the course of | ||
the function. | ||
*/ | ||
#[derive(Debug)] | ||
struct LastUpdateMetricsData { | ||
block_height: u64, | ||
} | ||
|
||
/// Responsible for collecting and updating metrics | ||
#[derive(Clone)] | ||
pub struct MetricsReporter { | ||
state: Arc<State>, | ||
network: IrohaNetwork, | ||
kura: Arc<Kura>, | ||
queue: Arc<Queue>, | ||
metrics: Metrics, | ||
last_update_metrics_mutex: Arc<Mutex<LastUpdateMetricsData>>, | ||
} | ||
|
||
impl MetricsReporter { | ||
/// Construct [`Self`] | ||
pub fn new( | ||
state: Arc<State>, | ||
network: IrohaNetwork, | ||
kura: Arc<Kura>, | ||
queue: Arc<Queue>, | ||
) -> Self { | ||
Self { | ||
state, | ||
network, | ||
queue, | ||
kura, | ||
metrics: Metrics::default(), | ||
last_update_metrics_mutex: Arc::new(Mutex::new(LastUpdateMetricsData { | ||
block_height: 0, | ||
})), | ||
} | ||
} | ||
|
||
/// Update the metrics on the state. | ||
/// | ||
/// # Errors | ||
/// - Domains fail to compose | ||
/// | ||
/// # Panics | ||
/// - If either mutex is poisoned | ||
#[allow(clippy::cast_precision_loss)] | ||
pub fn update_metrics(&self) -> Result<()> { | ||
let online_peers_count: u64 = self | ||
.network | ||
.online_peers( | ||
#[allow(clippy::disallowed_types)] | ||
std::collections::HashSet::len, | ||
) | ||
.try_into() | ||
.expect("casting usize to u64"); | ||
|
||
let state_view = self.state.view(); | ||
|
||
let mut last_guard = self.last_update_metrics_mutex.lock(); | ||
|
||
let start_index = last_guard.block_height; | ||
{ | ||
let mut block_index = start_index; | ||
while block_index < state_view.height() { | ||
let Some(block) = self.kura.get_block_by_height(block_index + 1) else { | ||
break; | ||
}; | ||
block_index += 1; | ||
let mut block_txs_accepted = 0; | ||
let mut block_txs_rejected = 0; | ||
for tx in block.transactions() { | ||
if tx.error.is_none() { | ||
block_txs_accepted += 1; | ||
} else { | ||
block_txs_rejected += 1; | ||
} | ||
} | ||
|
||
self.metrics | ||
.txs | ||
.with_label_values(&["accepted"]) | ||
.inc_by(block_txs_accepted); | ||
self.metrics | ||
.txs | ||
.with_label_values(&["rejected"]) | ||
.inc_by(block_txs_rejected); | ||
self.metrics | ||
.txs | ||
.with_label_values(&["total"]) | ||
.inc_by(block_txs_accepted + block_txs_rejected); | ||
self.metrics.block_height.inc(); | ||
} | ||
last_guard.block_height = block_index; | ||
} | ||
|
||
let new_tx_amounts = { | ||
let mut new_buf = Vec::new(); | ||
core::mem::swap(&mut new_buf, &mut state_view.new_tx_amounts.lock()); | ||
new_buf | ||
}; | ||
|
||
for amount in &new_tx_amounts { | ||
self.metrics.tx_amounts.observe(*amount); | ||
} | ||
|
||
#[allow(clippy::cast_possible_truncation)] | ||
if let Some(timestamp) = state_view.genesis_timestamp() { | ||
// this will overflow in 584942417years. | ||
self.metrics.uptime_since_genesis_ms.set( | ||
(current_time() - timestamp) | ||
.as_millis() | ||
.try_into() | ||
.expect("Timestamp should fit into u64"), | ||
) | ||
}; | ||
|
||
self.metrics.connected_peers.set(online_peers_count); | ||
|
||
self.metrics | ||
.domains | ||
.set(state_view.world().domains().len() as u64); | ||
for domain in state_view.world().domains_iter() { | ||
self.metrics | ||
.accounts | ||
.get_metric_with_label_values(&[domain.id.name.as_ref()]) | ||
.wrap_err("Failed to compose domains")? | ||
.set(domain.accounts.len() as u64); | ||
} | ||
|
||
self.metrics | ||
.view_changes | ||
.set(state_view.latest_block_view_change_index()); | ||
|
||
self.metrics.queue_size.set(self.queue.tx_len() as u64); | ||
|
||
Ok(()) | ||
} | ||
|
||
/// Access node metrics. | ||
pub fn metrics(&self) -> &Metrics { | ||
&self.metrics | ||
} | ||
} |
Oops, something went wrong.