Skip to content

Commit d4fb7fe

Browse files
committed
Unify participation metrics
1 parent b9d8e07 commit d4fb7fe

File tree

10 files changed

+105
-76
lines changed

10 files changed

+105
-76
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ cargo-fmt:
9595
check-benches:
9696
cargo check --workspace --benches
9797

98-
# Typechecks consensus code *without* allowing deprecated legacy arithmetic
98+
# Typechecks consensus code *without* allowing deprecated legacy arithmetic or metrics.
9999
check-consensus:
100100
cargo check --manifest-path=consensus/state_processing/Cargo.toml --no-default-features
101101

beacon_node/beacon_chain/src/block_verification.rs

Lines changed: 11 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,11 @@ use slot_clock::SlotClock;
5858
use ssz::Encode;
5959
use state_processing::{
6060
block_signature_verifier::{BlockSignatureVerifier, Error as BlockSignatureVerifierError},
61-
per_block_processing,
62-
per_epoch_processing::EpochProcessingSummary,
63-
per_slot_processing,
61+
per_block_processing, per_slot_processing,
6462
state_advance::partial_state_advance,
6563
BlockProcessingError, BlockSignatureStrategy, SlotProcessingError,
6664
};
6765
use std::borrow::Cow;
68-
use std::convert::TryFrom;
6966
use std::fs;
7067
use std::io::Write;
7168
use store::{Error as DBError, HotColdDB, HotStateSummary, KeyValueStore, StoreOp};
@@ -971,12 +968,19 @@ impl<'a, T: BeaconChainTypes> FullyVerifiedBlock<'a, T> {
971968
};
972969

973970
if let Some(summary) = per_slot_processing(&mut state, Some(state_root), &chain.spec)? {
974-
summaries.push(summary)
971+
// Expose Prometheus metrics.
972+
if let Err(e) = summary.observe_metrics() {
973+
error!(
974+
chain.log,
975+
"Failed to observe epoch summary metrics";
976+
"src" => "block_verification",
977+
"error" => ?e
978+
);
979+
}
980+
summaries.push(summary);
975981
}
976982
}
977983

978-
expose_participation_metrics(&summaries, &chain.log);
979-
980984
// If the block is sufficiently recent, notify the validator monitor.
981985
if let Some(slot) = chain.slot_clock.now() {
982986
let epoch = slot.epoch(T::EthSpec::slots_per_epoch());
@@ -1440,62 +1444,6 @@ fn verify_header_signature<T: BeaconChainTypes>(
14401444
}
14411445
}
14421446

1443-
fn expose_participation_metrics(summaries: &[EpochProcessingSummary], log: &Logger) {
1444-
if !cfg!(feature = "participation_metrics") {
1445-
return;
1446-
}
1447-
1448-
for summary in summaries {
1449-
match summary.previous_epoch_target_attesting_balance() {
1450-
Ok(target_balance) => {
1451-
metrics::maybe_set_float_gauge(
1452-
&metrics::PARTICIPATION_PREV_EPOCH_TARGET_ATTESTER,
1453-
participation_ratio(
1454-
target_balance,
1455-
summary.previous_epoch_total_active_balance(),
1456-
),
1457-
);
1458-
}
1459-
Err(e) => error!(
1460-
log,
1461-
"Unable to read target balance";
1462-
"error" => ?e,
1463-
),
1464-
}
1465-
1466-
match summary.previous_epoch_head_attesting_balance() {
1467-
Ok(head_balance) => {
1468-
metrics::maybe_set_float_gauge(
1469-
&metrics::PARTICIPATION_PREV_EPOCH_HEAD_ATTESTER,
1470-
participation_ratio(
1471-
head_balance,
1472-
summary.previous_epoch_total_active_balance(),
1473-
),
1474-
);
1475-
}
1476-
Err(e) => error!(
1477-
log,
1478-
"Unable to read head balance";
1479-
"error" => ?e,
1480-
),
1481-
}
1482-
}
1483-
}
1484-
1485-
fn participation_ratio(section: u64, total: u64) -> Option<f64> {
1486-
// Reduce the precision to help ensure we fit inside a u32.
1487-
const PRECISION: u64 = 100_000_000;
1488-
1489-
let section: f64 = u32::try_from(section / PRECISION).ok()?.into();
1490-
let total: f64 = u32::try_from(total / PRECISION).ok()?.into();
1491-
1492-
if total > 0_f64 {
1493-
Some(section / total)
1494-
} else {
1495-
None
1496-
}
1497-
}
1498-
14991447
fn write_state<T: EthSpec>(prefix: &str, state: &BeaconState<T>, log: &Logger) {
15001448
if WRITE_BLOCK_PROCESSING_SSZ {
15011449
let root = state.tree_hash_root();

beacon_node/beacon_chain/src/metrics.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -330,17 +330,6 @@ lazy_static! {
330330
pub static ref OP_POOL_NUM_VOLUNTARY_EXITS: Result<IntGauge> =
331331
try_create_int_gauge("beacon_op_pool_voluntary_exits_total", "Count of voluntary exits in the op pool");
332332

333-
/*
334-
* Participation Metrics
335-
*/
336-
pub static ref PARTICIPATION_PREV_EPOCH_TARGET_ATTESTER: Result<Gauge> = try_create_float_gauge(
337-
"beacon_participation_prev_epoch_target_attester",
338-
"Ratio of target-attesting balances to total balances"
339-
);
340-
pub static ref PARTICIPATION_PREV_EPOCH_HEAD_ATTESTER: Result<Gauge> = try_create_float_gauge(
341-
"beacon_participation_prev_epoch_head_attester",
342-
"Ratio of head-attesting balances to total balances"
343-
);
344333

345334
/*
346335
* Attestation Observation Metrics

beacon_node/beacon_chain/src/state_advance_timer.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,16 @@ fn advance_head<T: BeaconChainTypes>(
233233
if let Some(summary) = per_slot_processing(&mut state, state_root, &beacon_chain.spec)
234234
.map_err(BeaconChainError::from)?
235235
{
236+
// Expose Prometheus metrics.
237+
if let Err(e) = summary.observe_metrics() {
238+
error!(
239+
log,
240+
"Failed to observe epoch summary metrics";
241+
"src" => "state_advance_timer",
242+
"error" => ?e
243+
);
244+
}
245+
236246
// Only notify the validator monitor for recent blocks.
237247
if state.current_epoch() + VALIDATOR_MONITOR_HISTORIC_EPOCHS as u64
238248
>= current_slot.epoch(T::EthSpec::slots_per_epoch())

consensus/state_processing/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,14 @@ eth2_hashing = "0.1.0"
2929
int_to_bytes = { path = "../int_to_bytes" }
3030
smallvec = "1.6.1"
3131
arbitrary = { version = "0.4.6", features = ["derive"], optional = true }
32+
lighthouse_metrics = { path = "../../common/lighthouse_metrics", optional = true }
33+
lazy_static = { version = "1.4.0", optional = true }
3234

3335
[features]
34-
default = ["legacy-arith"]
36+
default = ["legacy-arith", "metrics"]
3537
fake_crypto = ["bls/fake_crypto"]
3638
legacy-arith = ["types/legacy-arith"]
39+
metrics = ["lighthouse_metrics", "lazy_static"]
3740
arbitrary-fuzz = [
3841
"arbitrary",
3942
"types/arbitrary-fuzz",

consensus/state_processing/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#[macro_use]
1616
mod macros;
17+
mod metrics;
1718

1819
pub mod common;
1920
pub mod genesis;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#[cfg(feature = "metrics")]
2+
pub use only_if_enabled::*;
3+
4+
#[cfg(feature = "metrics")]
5+
pub mod only_if_enabled {
6+
use lazy_static::lazy_static;
7+
pub use lighthouse_metrics::*;
8+
9+
lazy_static! {
10+
/*
11+
* Participation Metrics
12+
*/
13+
pub static ref PARTICIPATION_PREV_EPOCH_HEAD_ATTESTING_GWEI_TOTAL: Result<IntGauge> = try_create_int_gauge(
14+
"beacon_participation_prev_epoch_head_attesting_gwei_total",
15+
"Total effective balance (gwei) of validators who attested to the head in the previous epoch"
16+
);
17+
pub static ref PARTICIPATION_PREV_EPOCH_TARGET_ATTESTING_GWEI_TOTAL: Result<IntGauge> = try_create_int_gauge(
18+
"beacon_participation_prev_epoch_target_attesting_gwei_total",
19+
"Total effective balance (gwei) of validators who attested to the target in the previous epoch"
20+
);
21+
pub static ref PARTICIPATION_PREV_EPOCH_SOURCE_ATTESTING_GWEI_TOTAL: Result<IntGauge> = try_create_int_gauge(
22+
"beacon_participation_prev_epoch_source_attesting_gwei_total",
23+
"Total effective balance (gwei) of validators who attested to the source in the previous epoch"
24+
);
25+
pub static ref PARTICIPATION_PREV_EPOCH_ACTIVE_GWEI_TOTAL: Result<IntGauge> = try_create_int_gauge(
26+
"beacon_participation_prev_epoch_active_gwei_total",
27+
"Total effective balance (gwei) of validators active in the previous epoch"
28+
);
29+
}
30+
}

consensus/state_processing/src/per_epoch_processing/altair/participation_cache.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,11 @@ impl ParticipationCache {
303303
.total_flag_balance(TIMELY_TARGET_FLAG_INDEX)
304304
}
305305

306+
pub fn previous_epoch_source_attesting_balance(&self) -> Result<u64, Error> {
307+
self.previous_epoch_participation
308+
.total_flag_balance(TIMELY_SOURCE_FLAG_INDEX)
309+
}
310+
306311
pub fn previous_epoch_head_attesting_balance(&self) -> Result<u64, Error> {
307312
self.previous_epoch_participation
308313
.total_flag_balance(TIMELY_HEAD_FLAG_INDEX)

consensus/state_processing/src/per_epoch_processing/epoch_processing_summary.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use super::{
33
base::{TotalBalances, ValidatorStatus},
44
validator_statuses::InclusionInfo,
55
};
6+
use crate::metrics;
67

78
/// Provides a summary of validator participation during the epoch.
89
#[derive(PartialEq, Debug)]
@@ -17,6 +18,29 @@ pub enum EpochProcessingSummary {
1718
}
1819

1920
impl EpochProcessingSummary {
21+
/// Updates some Prometheus metrics with some values in `self`.
22+
#[cfg(feature = "metrics")]
23+
pub fn observe_metrics(&self) -> Result<(), ParticipationCacheError> {
24+
metrics::set_gauge(
25+
&metrics::PARTICIPATION_PREV_EPOCH_HEAD_ATTESTING_GWEI_TOTAL,
26+
self.previous_epoch_head_attesting_balance()? as i64,
27+
);
28+
metrics::set_gauge(
29+
&metrics::PARTICIPATION_PREV_EPOCH_TARGET_ATTESTING_GWEI_TOTAL,
30+
self.previous_epoch_target_attesting_balance()? as i64,
31+
);
32+
metrics::set_gauge(
33+
&metrics::PARTICIPATION_PREV_EPOCH_SOURCE_ATTESTING_GWEI_TOTAL,
34+
self.previous_epoch_source_attesting_balance()? as i64,
35+
);
36+
metrics::set_gauge(
37+
&metrics::PARTICIPATION_PREV_EPOCH_ACTIVE_GWEI_TOTAL,
38+
self.previous_epoch_total_active_balance() as i64,
39+
);
40+
41+
Ok(())
42+
}
43+
2044
/// Returns the sum of the effective balance of all validators in the current epoch.
2145
pub fn current_epoch_total_active_balance(&self) -> u64 {
2246
match self {
@@ -127,6 +151,24 @@ impl EpochProcessingSummary {
127151
}
128152
}
129153

154+
/// Returns the sum of the effective balance of all validators in the previous epoch who
155+
/// included an attestation that matched the source.
156+
///
157+
/// ## Differences between Base and Altair
158+
///
159+
/// - Base: any attestation can match the source.
160+
/// - Altair: only "timely" attestations can match the source.
161+
pub fn previous_epoch_source_attesting_balance(&self) -> Result<u64, ParticipationCacheError> {
162+
match self {
163+
EpochProcessingSummary::Base { total_balances, .. } => {
164+
Ok(total_balances.previous_epoch_attesters())
165+
}
166+
EpochProcessingSummary::Altair {
167+
participation_cache,
168+
} => participation_cache.previous_epoch_source_attesting_balance(),
169+
}
170+
}
171+
130172
/// Returns `true` if `val_index` was included in the active validator indices in the previous
131173
/// epoch *and* the validator is not slashed.
132174
///

0 commit comments

Comments
 (0)