diff --git a/eth_validator_watcher/blocks.py b/eth_validator_watcher/blocks.py index a483642..bad2a7f 100644 --- a/eth_validator_watcher/blocks.py +++ b/eth_validator_watcher/blocks.py @@ -14,9 +14,9 @@ def process_block(validators: WatchedValidators, schedule: ProposerSchedule, slo return if has_block: - validator.proposed_blocks_total += 1 + validator.proposed_blocks.append(slot_id) else: - validator.missed_blocks_total += 1 + validator.missed_blocks.append(slot_id) def process_finalized_block(validators: WatchedValidators, schedule: ProposerSchedule, slot_id: int, has_block: bool): @@ -29,9 +29,9 @@ def process_finalized_block(validators: WatchedValidators, schedule: ProposerSch return if has_block: - validator.proposed_blocks_finalized_total += 1 + validator.proposed_blocks_finalized.append(slot_id) else: - validator.missed_blocks_finalized_total += 1 + validator.missed_blocks_finalized.append(slot_id) def process_future_blocks(validators: WatchedValidators, schedule: ProposerSchedule, slot_id: int): @@ -42,4 +42,4 @@ def process_future_blocks(validators: WatchedValidators, schedule: ProposerSched if validator is None: continue - validator.future_blocks_proposal += 1 + validator.future_blocks_proposal.append(slot_id) diff --git a/eth_validator_watcher/entrypoint.py b/eth_validator_watcher/entrypoint.py index 90c608e..922a324 100644 --- a/eth_validator_watcher/entrypoint.py +++ b/eth_validator_watcher/entrypoint.py @@ -100,7 +100,7 @@ def _update_metrics(self, watched_validators: WatchedValidators, epoch: int, slo # there is a log of entries here, this makes code here a bit # more complex and entangled. - metrics = compute_validator_metrics(watched_validators.validators()) + metrics = compute_validator_metrics(watched_validators.validators(), slot) for label, m in metrics.items(): for status in Validators.DataItem.StatusEnum: diff --git a/eth_validator_watcher/metrics.py b/eth_validator_watcher/metrics.py index ba3abdb..2dc5416 100644 --- a/eth_validator_watcher/metrics.py +++ b/eth_validator_watcher/metrics.py @@ -7,6 +7,7 @@ from prometheus_client import Counter, Gauge +from .utils import LABEL_SCOPE_WATCHED from .watched_validators import WatchedValidator @@ -77,7 +78,7 @@ class AggregatedMetricsByLabel(): future_blocks: int = 0 -def compute_validator_metrics(validators: dict[int, WatchedValidator]) -> dict[str, AggregatedMetricsByLabel]: +def compute_validator_metrics(validators: dict[int, WatchedValidator], slot: int) -> dict[str, AggregatedMetricsByLabel]: """Compute the metrics from a list of validators. Parameters: @@ -123,12 +124,22 @@ def compute_validator_metrics(validators: dict[int, WatchedValidator]) -> dict[s m.missed_attestations += int(v.missed_attestation == True) m.missed_consecutive_attestations += int(v.previous_missed_attestation == True and v.missed_attestation == True) - m.proposed_blocks += v.proposed_blocks_total - m.missed_blocks += v.missed_blocks_total - m.proposed_finalized_blocks += v.proposed_blocks_finalized_total - m.missed_finalized_blocks += v.missed_blocks_finalized_total - - m.future_blocks += v.future_blocks_proposal + m.proposed_blocks += len(v.proposed_blocks) + m.missed_blocks += len(v.missed_blocks) + m.proposed_finalized_blocks += len(v.proposed_blocks_finalized) + m.missed_finalized_blocks += len(v.missed_blocks_finalized) + + m.future_blocks += len(v.future_blocks_proposal) + + if label == LABEL_SCOPE_WATCHED: + for proposed in v.proposed_blocks: + logging.info(f"✨ Validator {v.pubkey} proposed block at head slot={proposed} ✨") + for proposed in v.proposed_blocks_finalized: + logging.info(f"✅ Validator {v.pubkey} proposed block at finalized slot={proposed} ✅") + for miss in v.missed_blocks: + logging.info(f"❗Validator {v.pubkey} missed blocks at head slot={miss} ❗") + for miss in v.missed_blocks_finalized: + logging.info(f"❌ Validator {v.pubkey} missed blocks at finalized slot={miss} ❌") v.reset_counters() diff --git a/eth_validator_watcher/watched_validators.py b/eth_validator_watcher/watched_validators.py index c0cdae8..3838673 100644 --- a/eth_validator_watcher/watched_validators.py +++ b/eth_validator_watcher/watched_validators.py @@ -62,11 +62,11 @@ def __init__(self): # Counters (incremented continuously) ; implies to use rates() # on the Prometheus side to have meaningful graphs. - self.missed_blocks_total : int = 0 - self.missed_blocks_finalized_total : int = 0 - self.proposed_blocks_total : int = 0 - self.proposed_blocks_finalized_total : int = 0 - self.future_blocks_proposal : int = 0 + self.missed_blocks : list = [] + self.missed_blocks_finalized : list = [] + self.proposed_blocks : list = [] + self.proposed_blocks_finalized : list = [] + self.future_blocks_proposal : list = [] @property def pubkey(self) -> str: @@ -129,11 +129,11 @@ def process_liveness(self, liveness: ValidatorsLivenessResponse.Data): def reset_counters(self): """Reset the counters for the next run. """ - self.missed_blocks_total = 0 - self.missed_blocks_finalized_total = 0 - self.proposed_blocks_total = 0 - self.proposed_blocks_finalized_total = 0 - self.future_blocks_proposal = 0 + self.missed_blocks.clear() + self.missed_blocks_finalized.clear() + self.proposed_blocks.clear() + self.proposed_blocks_finalized.clear() + self.future_blocks_proposal.clear()