Expose certain validator_monitor
metrics to the HTTP API (#3760)
## Issue Addressed #3724 ## Proposed Changes Exposes certain `validator_monitor` as an endpoint on the HTTP API. Will only return metrics for validators which are actively being monitored. ### Usage ```bash curl -X GET "http://localhost:5052/lighthouse/ui/validator_metrics" -H "accept: application/json" | jq ``` ```json { "data": { "validators": { "12345": { "attestation_hits": 10, "attestation_misses": 0, "attestation_hit_percentage": 100, "attestation_head_hits": 10, "attestation_head_misses": 0, "attestation_head_hit_percentage": 100, "attestation_target_hits": 5, "attestation_target_misses": 5, "attestation_target_hit_percentage": 50 } } } } ``` ## Additional Info Based on #3756 which should be merged first.
This commit is contained in:
parent
84392d63fa
commit
8cb9b5e126
@ -22,7 +22,7 @@ pub mod fork_revert;
|
|||||||
mod head_tracker;
|
mod head_tracker;
|
||||||
pub mod historical_blocks;
|
pub mod historical_blocks;
|
||||||
pub mod merge_readiness;
|
pub mod merge_readiness;
|
||||||
mod metrics;
|
pub mod metrics;
|
||||||
pub mod migrate;
|
pub mod migrate;
|
||||||
mod naive_aggregation_pool;
|
mod naive_aggregation_pool;
|
||||||
mod observed_aggregates;
|
mod observed_aggregates;
|
||||||
|
@ -629,6 +629,14 @@ impl<T: EthSpec> ValidatorMonitor<T> {
|
|||||||
self.validators.len()
|
self.validators.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the `id`'s of all monitored validators.
|
||||||
|
pub fn get_all_monitored_validators(&self) -> Vec<String> {
|
||||||
|
self.validators
|
||||||
|
.iter()
|
||||||
|
.map(|(_, val)| val.id.clone())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
/// If `self.auto_register == true`, add the `validator_index` to `self.monitored_validators`.
|
/// If `self.auto_register == true`, add the `validator_index` to `self.monitored_validators`.
|
||||||
/// Otherwise, do nothing.
|
/// Otherwise, do nothing.
|
||||||
pub fn auto_register_local_validator(&mut self, validator_index: u64) {
|
pub fn auto_register_local_validator(&mut self, validator_index: u64) {
|
||||||
|
@ -2899,6 +2899,22 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// POST lighthouse/ui/validator_metrics
|
||||||
|
let post_lighthouse_ui_validator_metrics = warp::path("lighthouse")
|
||||||
|
.and(warp::path("ui"))
|
||||||
|
.and(warp::path("validator_metrics"))
|
||||||
|
.and(warp::path::end())
|
||||||
|
.and(warp::body::json())
|
||||||
|
.and(chain_filter.clone())
|
||||||
|
.and_then(
|
||||||
|
|request_data: ui::ValidatorMetricsRequestData, chain: Arc<BeaconChain<T>>| {
|
||||||
|
blocking_json_task(move || {
|
||||||
|
ui::post_validator_monitor_metrics(request_data, chain)
|
||||||
|
.map(api_types::GenericResponse::from)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// GET lighthouse/syncing
|
// GET lighthouse/syncing
|
||||||
let get_lighthouse_syncing = warp::path("lighthouse")
|
let get_lighthouse_syncing = warp::path("lighthouse")
|
||||||
.and(warp::path("syncing"))
|
.and(warp::path("syncing"))
|
||||||
@ -3349,6 +3365,7 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
.or(get_validator_sync_committee_contribution.boxed())
|
.or(get_validator_sync_committee_contribution.boxed())
|
||||||
.or(get_lighthouse_health.boxed())
|
.or(get_lighthouse_health.boxed())
|
||||||
.or(get_lighthouse_ui_health.boxed())
|
.or(get_lighthouse_ui_health.boxed())
|
||||||
|
.or(get_lighthouse_ui_validator_count.boxed())
|
||||||
.or(get_lighthouse_syncing.boxed())
|
.or(get_lighthouse_syncing.boxed())
|
||||||
.or(get_lighthouse_nat.boxed())
|
.or(get_lighthouse_nat.boxed())
|
||||||
.or(get_lighthouse_peers.boxed())
|
.or(get_lighthouse_peers.boxed())
|
||||||
@ -3366,7 +3383,6 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
.or(get_lighthouse_attestation_performance.boxed())
|
.or(get_lighthouse_attestation_performance.boxed())
|
||||||
.or(get_lighthouse_block_packing_efficiency.boxed())
|
.or(get_lighthouse_block_packing_efficiency.boxed())
|
||||||
.or(get_lighthouse_merge_readiness.boxed())
|
.or(get_lighthouse_merge_readiness.boxed())
|
||||||
.or(get_lighthouse_ui_validator_count.boxed())
|
|
||||||
.or(get_events.boxed()),
|
.or(get_events.boxed()),
|
||||||
)
|
)
|
||||||
.boxed()
|
.boxed()
|
||||||
@ -3390,7 +3406,8 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
.or(post_lighthouse_liveness.boxed())
|
.or(post_lighthouse_liveness.boxed())
|
||||||
.or(post_lighthouse_database_reconstruct.boxed())
|
.or(post_lighthouse_database_reconstruct.boxed())
|
||||||
.or(post_lighthouse_database_historical_blocks.boxed())
|
.or(post_lighthouse_database_historical_blocks.boxed())
|
||||||
.or(post_lighthouse_block_rewards.boxed()),
|
.or(post_lighthouse_block_rewards.boxed())
|
||||||
|
.or(post_lighthouse_ui_validator_metrics.boxed()),
|
||||||
))
|
))
|
||||||
.recover(warp_utils::reject::handle_rejection)
|
.recover(warp_utils::reject::handle_rejection)
|
||||||
.with(slog_logging(log.clone()))
|
.with(slog_logging(log.clone()))
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes};
|
use beacon_chain::{metrics, BeaconChain, BeaconChainError, BeaconChainTypes};
|
||||||
use eth2::types::ValidatorStatus;
|
use eth2::types::ValidatorStatus;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use warp_utils::reject::beacon_chain_error;
|
use warp_utils::reject::beacon_chain_error;
|
||||||
|
|
||||||
#[derive(Debug, Default, PartialEq, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct ValidatorCountResponse {
|
pub struct ValidatorCountResponse {
|
||||||
pub active_ongoing: u64,
|
pub active_ongoing: u64,
|
||||||
pub active_exiting: u64,
|
pub active_exiting: u64,
|
||||||
@ -69,3 +70,126 @@ pub fn get_validator_count<T: BeaconChainTypes>(
|
|||||||
exited_slashed,
|
exited_slashed,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct ValidatorMetricsRequestData {
|
||||||
|
indices: Vec<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct ValidatorMetrics {
|
||||||
|
attestation_hits: u64,
|
||||||
|
attestation_misses: u64,
|
||||||
|
attestation_hit_percentage: f64,
|
||||||
|
attestation_head_hits: u64,
|
||||||
|
attestation_head_misses: u64,
|
||||||
|
attestation_head_hit_percentage: f64,
|
||||||
|
attestation_target_hits: u64,
|
||||||
|
attestation_target_misses: u64,
|
||||||
|
attestation_target_hit_percentage: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct ValidatorMetricsResponse {
|
||||||
|
validators: HashMap<String, ValidatorMetrics>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn post_validator_monitor_metrics<T: BeaconChainTypes>(
|
||||||
|
request_data: ValidatorMetricsRequestData,
|
||||||
|
chain: Arc<BeaconChain<T>>,
|
||||||
|
) -> Result<ValidatorMetricsResponse, warp::Rejection> {
|
||||||
|
let validator_ids = chain
|
||||||
|
.validator_monitor
|
||||||
|
.read()
|
||||||
|
.get_all_monitored_validators()
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect::<HashSet<String>>();
|
||||||
|
|
||||||
|
let indices = request_data
|
||||||
|
.indices
|
||||||
|
.iter()
|
||||||
|
.map(|index| index.to_string())
|
||||||
|
.collect::<HashSet<String>>();
|
||||||
|
|
||||||
|
let ids = validator_ids
|
||||||
|
.intersection(&indices)
|
||||||
|
.collect::<HashSet<&String>>();
|
||||||
|
|
||||||
|
let mut validators = HashMap::new();
|
||||||
|
|
||||||
|
for id in ids {
|
||||||
|
let attestation_hits = metrics::get_int_counter(
|
||||||
|
&metrics::VALIDATOR_MONITOR_PREV_EPOCH_ON_CHAIN_ATTESTER_HIT,
|
||||||
|
&[id],
|
||||||
|
)
|
||||||
|
.map(|counter| counter.get())
|
||||||
|
.unwrap_or(0);
|
||||||
|
let attestation_misses = metrics::get_int_counter(
|
||||||
|
&metrics::VALIDATOR_MONITOR_PREV_EPOCH_ON_CHAIN_ATTESTER_MISS,
|
||||||
|
&[id],
|
||||||
|
)
|
||||||
|
.map(|counter| counter.get())
|
||||||
|
.unwrap_or(0);
|
||||||
|
let attestations = attestation_hits + attestation_misses;
|
||||||
|
let attestation_hit_percentage: f64 = if attestations == 0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
(100 * attestation_hits / attestations) as f64
|
||||||
|
};
|
||||||
|
|
||||||
|
let attestation_head_hits = metrics::get_int_counter(
|
||||||
|
&metrics::VALIDATOR_MONITOR_PREV_EPOCH_ON_CHAIN_HEAD_ATTESTER_HIT,
|
||||||
|
&[id],
|
||||||
|
)
|
||||||
|
.map(|counter| counter.get())
|
||||||
|
.unwrap_or(0);
|
||||||
|
let attestation_head_misses = metrics::get_int_counter(
|
||||||
|
&metrics::VALIDATOR_MONITOR_PREV_EPOCH_ON_CHAIN_HEAD_ATTESTER_MISS,
|
||||||
|
&[id],
|
||||||
|
)
|
||||||
|
.map(|counter| counter.get())
|
||||||
|
.unwrap_or(0);
|
||||||
|
let head_attestations = attestation_head_hits + attestation_head_misses;
|
||||||
|
let attestation_head_hit_percentage: f64 = if head_attestations == 0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
(100 * attestation_head_hits / head_attestations) as f64
|
||||||
|
};
|
||||||
|
|
||||||
|
let attestation_target_hits = metrics::get_int_counter(
|
||||||
|
&metrics::VALIDATOR_MONITOR_PREV_EPOCH_ON_CHAIN_TARGET_ATTESTER_HIT,
|
||||||
|
&[id],
|
||||||
|
)
|
||||||
|
.map(|counter| counter.get())
|
||||||
|
.unwrap_or(0);
|
||||||
|
let attestation_target_misses = metrics::get_int_counter(
|
||||||
|
&metrics::VALIDATOR_MONITOR_PREV_EPOCH_ON_CHAIN_TARGET_ATTESTER_MISS,
|
||||||
|
&[id],
|
||||||
|
)
|
||||||
|
.map(|counter| counter.get())
|
||||||
|
.unwrap_or(0);
|
||||||
|
let target_attestations = attestation_target_hits + attestation_target_misses;
|
||||||
|
let attestation_target_hit_percentage: f64 = if target_attestations == 0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
(100 * attestation_target_hits / target_attestations) as f64
|
||||||
|
};
|
||||||
|
|
||||||
|
let metrics = ValidatorMetrics {
|
||||||
|
attestation_hits,
|
||||||
|
attestation_misses,
|
||||||
|
attestation_hit_percentage,
|
||||||
|
attestation_head_hits,
|
||||||
|
attestation_head_misses,
|
||||||
|
attestation_head_hit_percentage,
|
||||||
|
attestation_target_hits,
|
||||||
|
attestation_target_misses,
|
||||||
|
attestation_target_hit_percentage,
|
||||||
|
};
|
||||||
|
|
||||||
|
validators.insert(id.clone(), metrics);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ValidatorMetricsResponse { validators })
|
||||||
|
}
|
||||||
|
@ -121,6 +121,33 @@ curl -X GET "http://localhost:5052/lighthouse/ui/validator_count" -H "accept: ap
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `/lighthouse/ui/validator_metrics`
|
||||||
|
Re-exposes certain metrics from the validator monitor to the HTTP API.
|
||||||
|
Will only return metrics for the validators currently being monitored and are present in the POST data.
|
||||||
|
```bash
|
||||||
|
curl -X POST "http://localhost:5052/lighthouse/ui/validator_metrics" -d '{"indices": [12345]}' -H "Content-Type: application/json" | jq
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"validators": {
|
||||||
|
"12345": {
|
||||||
|
"attestation_hits": 10,
|
||||||
|
"attestation_misses": 0,
|
||||||
|
"attestation_hit_percentage": 100,
|
||||||
|
"attestation_head_hits": 10,
|
||||||
|
"attestation_head_misses": 0,
|
||||||
|
"attestation_head_hit_percentage": 100,
|
||||||
|
"attestation_target_hits": 5,
|
||||||
|
"attestation_target_misses": 5,
|
||||||
|
"attestation_target_hit_percentage": 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### `/lighthouse/syncing`
|
### `/lighthouse/syncing`
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
Loading…
Reference in New Issue
Block a user