Skip to content

Commit

Permalink
feat: compute ideal/actual consensus rewards per scope
Browse files Browse the repository at this point in the history
  • Loading branch information
aimxhaisse committed Apr 4, 2024
1 parent dab0dba commit 2d6dfdb
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 17 deletions.
44 changes: 27 additions & 17 deletions eth_validator_watcher/entrypoint_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
app = typer.Typer(add_completion=False)


def pct(a: int, b: int) -> float:
def pct(a: int, b: int, inclusive: bool=False) -> float:
"""Helper function to calculate the percentage of a over b.
"""
total = a + b
total = a + b if not inclusive else b
if total == 0:
return 0.0
return float(a / total) * 100.0
Expand Down Expand Up @@ -162,12 +162,15 @@ def _update_metrics(self, watched_validators: WatchedValidators, epoch: int, slo

validator_status_count: dict[str, dict[StatusEnum, int]] = defaultdict(partial(defaultdict, int))

validator_suboptimal_source_count: dict[str, int] = defaultdict(int)
validator_suboptimal_target_count: dict[str, int] = defaultdict(int)
validator_suboptimal_head_count: dict[str, int] = defaultdict(int)
validator_optimal_source_count: dict[str, int] = defaultdict(int)
validator_optimal_target_count: dict[str, int] = defaultdict(int)
validator_optimal_head_count: dict[str, int] = defaultdict(int)
suboptimal_source_count: dict[str, int] = defaultdict(int)
suboptimal_target_count: dict[str, int] = defaultdict(int)
suboptimal_head_count: dict[str, int] = defaultdict(int)
optimal_source_count: dict[str, int] = defaultdict(int)
optimal_target_count: dict[str, int] = defaultdict(int)
optimal_head_count: dict[str, int] = defaultdict(int)

ideal_consensus_reward: dict[str, int] = defaultdict(int)
actual_consensus_reward: dict[str, int] = defaultdict(int)

labels = set()

Expand All @@ -179,12 +182,15 @@ def _update_metrics(self, watched_validators: WatchedValidators, epoch: int, slo
# Looks weird but we want to explicitly have labels set
# for each set of labels even if they aren't validating
# (in which case the validator attributes are None).
validator_suboptimal_source_count[label] += int(validator.suboptimal_source == True)
validator_suboptimal_target_count[label] += int(validator.suboptimal_target == True)
validator_suboptimal_head_count[label] += int(validator.suboptimal_head == True)
validator_optimal_source_count[label] += int(validator.suboptimal_source == False)
validator_optimal_target_count[label] += int(validator.suboptimal_target == False)
validator_optimal_head_count[label] += int(validator.suboptimal_head == False)
suboptimal_source_count[label] += int(validator.suboptimal_source == True)
suboptimal_target_count[label] += int(validator.suboptimal_target == True)
suboptimal_head_count[label] += int(validator.suboptimal_head == True)
optimal_source_count[label] += int(validator.suboptimal_source == False)
optimal_target_count[label] += int(validator.suboptimal_target == False)
optimal_head_count[label] += int(validator.suboptimal_head == False)

ideal_consensus_reward[label] += validator.ideal_consensus_reward or 0
actual_consensus_reward[label] += validator.actual_consensus_reward or 0

labels.add(label)

Expand All @@ -193,9 +199,13 @@ def _update_metrics(self, watched_validators: WatchedValidators, epoch: int, slo
self._metrics.eth_validator_status_count.labels(label, status.name).set(count)

for label in labels:
self._metrics.eth_suboptimal_sources_rate.labels(label).set(pct(validator_suboptimal_source_count[label], validator_optimal_source_count[label]))
self._metrics.eth_suboptimal_targets_rate.labels(label).set(pct(validator_suboptimal_target_count[label], validator_optimal_target_count[label]))
self._metrics.eth_suboptimal_heads_rate.labels(label).set(pct(validator_suboptimal_head_count[label], validator_optimal_head_count[label]))
self._metrics.eth_suboptimal_sources_rate.labels(label).set(pct(suboptimal_source_count[label], optimal_source_count[label]))
self._metrics.eth_suboptimal_targets_rate.labels(label).set(pct(suboptimal_target_count[label], optimal_target_count[label]))
self._metrics.eth_suboptimal_heads_rate.labels(label).set(pct(suboptimal_head_count[label], optimal_head_count[label]))

self._metrics.eth_ideal_consensus_rewards.labels(label).set(ideal_consensus_reward[label])
self._metrics.eth_actual_consensus_rewards.labels(label).set(actual_consensus_reward[label])
self._metrics.eth_consensus_rewards_rate.labels(label).set(pct(actual_consensus_reward[label], ideal_consensus_reward[label], True))

if not self._metrics_started:
start_http_server(self._cfg.metrics_port)
Expand Down
6 changes: 6 additions & 0 deletions eth_validator_watcher/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ class PrometheusMetrics:
eth_suboptimal_sources_rate: Gauge
eth_suboptimal_targets_rate: Gauge
eth_suboptimal_heads_rate: Gauge
eth_ideal_consensus_rewards: Gauge
eth_actual_consensus_rewards: Gauge
eth_consensus_rewards_rate: Gauge


def get_prometheus_metrics() -> PrometheusMetrics:
Expand All @@ -38,6 +41,9 @@ def get_prometheus_metrics() -> PrometheusMetrics:
eth_suboptimal_sources_rate=Gauge("eth_suboptimal_sources_rate", "Suboptimal sources rate", ['scope']),
eth_suboptimal_targets_rate=Gauge("eth_suboptimal_targets_rate", "Suboptimal targets rate", ['scope']),
eth_suboptimal_heads_rate=Gauge("eth_suboptimal_heads_rate", "Suboptimal heads rate", ['scope']),
eth_ideal_consensus_rewards=Gauge("eth_ideal_consensus_rewards", "Ideal consensus rewards", ['scope']),
eth_actual_consensus_rewards=Gauge("eth_actual_consensus_rewards", "Actual consensus rewards", ['scope']),
eth_consensus_rewards_rate=Gauge("eth_consensus_rewards_rate", "Consensus rewards rate", ['scope']),
)

return _metrics

0 comments on commit 2d6dfdb

Please sign in to comment.