Skip to main content

zebra_state/service/finalized_state/zebra_db/
metrics.rs

1//! Provides high-level database metrics.
2
3use zebra_chain::{
4    amount::NonNegative,
5    block::{self, Block},
6    value_balance::ValueBalance,
7};
8
9/// Update metrics before committing a block.
10///
11/// The metrics are updated after contextually validating a block,
12/// but before writing its batch to the state.
13pub(crate) fn block_precommit_metrics(block: &Block, hash: block::Hash, height: block::Height) {
14    let transaction_count = block.transactions.len();
15    let transparent_prevout_count = block
16        .transactions
17        .iter()
18        .flat_map(|t| t.inputs().iter())
19        .count()
20        // Each block has a single coinbase input which is not a previous output.
21        - 1;
22    let transparent_newout_count = block
23        .transactions
24        .iter()
25        .flat_map(|t| t.outputs().iter())
26        .count();
27
28    let sprout_nullifier_count = block.sprout_nullifiers().count();
29    let sapling_nullifier_count = block.sapling_nullifiers().count();
30    let orchard_nullifier_count = block.orchard_nullifiers().count();
31
32    tracing::debug!(
33        ?hash,
34        ?height,
35        transaction_count,
36        transparent_prevout_count,
37        transparent_newout_count,
38        sprout_nullifier_count,
39        sapling_nullifier_count,
40        orchard_nullifier_count,
41        "preparing to commit finalized {:?}block",
42        if height.is_min() { "genesis " } else { "" }
43    );
44
45    metrics::counter!("state.finalized.block.count").increment(1);
46    metrics::gauge!("state.finalized.block.height").set(height.0 as f64);
47
48    metrics::counter!("state.finalized.cumulative.transactions")
49        .increment(transaction_count as u64);
50
51    metrics::counter!("state.finalized.cumulative.sprout_nullifiers")
52        .increment(sprout_nullifier_count as u64);
53    metrics::counter!("state.finalized.cumulative.sapling_nullifiers")
54        .increment(sapling_nullifier_count as u64);
55    metrics::counter!("state.finalized.cumulative.orchard_nullifiers")
56        .increment(orchard_nullifier_count as u64);
57
58    // The outputs from the genesis block can't be spent, so we skip them here.
59    if !height.is_min() {
60        metrics::counter!("state.finalized.cumulative.transparent_prevouts")
61            .increment(transparent_prevout_count as u64);
62        metrics::counter!("state.finalized.cumulative.transparent_newouts")
63            .increment(transparent_newout_count as u64);
64    }
65}
66
67/// Update value pool metrics after calculating the new chain value pool.
68///
69/// These metrics expose the current balances of each shielded pool and total supply
70/// for monitoring and observability purposes.
71///
72/// These metrics enable:
73/// - Visualizing pool balances over time in Grafana dashboards
74/// - Setting up alerts for anomalous conditions
75/// - Monitoring total chain supply
76///
77/// The values are in zatoshis (1 ZEC = 100,000,000 zatoshis).
78pub(crate) fn value_pool_metrics(value_pool: &ValueBalance<NonNegative>) {
79    // Individual pool balances (zatoshis)
80    metrics::gauge!("state.finalized.value_pool.transparent")
81        .set(u64::from(value_pool.transparent_amount()) as f64);
82    metrics::gauge!("state.finalized.value_pool.sprout")
83        .set(u64::from(value_pool.sprout_amount()) as f64);
84    metrics::gauge!("state.finalized.value_pool.sapling")
85        .set(u64::from(value_pool.sapling_amount()) as f64);
86    metrics::gauge!("state.finalized.value_pool.orchard")
87        .set(u64::from(value_pool.orchard_amount()) as f64);
88    metrics::gauge!("state.finalized.value_pool.deferred")
89        .set(u64::from(value_pool.deferred_amount()) as f64);
90
91    // Total chain supply (sum of all pools)
92    let total_supply = u64::from(value_pool.transparent_amount())
93        + u64::from(value_pool.sprout_amount())
94        + u64::from(value_pool.sapling_amount())
95        + u64::from(value_pool.orchard_amount())
96        + u64::from(value_pool.deferred_amount());
97    metrics::gauge!("state.finalized.chain_supply.total").set(total_supply as f64);
98}