Implement lean_attestation_committee_subnet metric#243
Conversation
Register and set the metric at P2P startup with the computed subnet ID (validator_id % attestation_committee_count), per the leanMetrics spec. Non-validator nodes default to subnet 0.
🤖 Kimi Code ReviewReview SummaryThe PR adds a metric to expose the node's attestation committee subnet ID. Overall, the implementation is correct but has a few minor issues. Issues Found
Minor Observations
Automated review by Kimi (Moonshot AI) · custom prompt |
🤖 Codex Code Review
No consensus-critical logic (fork choice, attestation validation, justification/finalization, state transition, XMSS, SSZ) is modified in this PR. Performance impact is negligible. Automated review by OpenAI Codex · custom prompt |
🤖 Claude Code ReviewNow I have everything I need for the review. PR Review: Implement
|
Greptile SummaryThis PR exposes the pre-computed attestation committee subnet ID as a Prometheus
Confidence Score: 5/5
|
| Filename | Overview |
|---|---|
| crates/net/p2p/src/metrics.rs | Adds set_attestation_committee_subnet with a function-scoped LazyLock<IntGauge>; logic is correct but the scoping pattern is inconsistent with the module-level statics used for every other metric in this file. |
| crates/net/p2p/src/lib.rs | Calls set_attestation_committee_subnet(subnet_id.unwrap_or(0)) immediately after computing the subnet ID; placement and default value (0 for non-validators) are correct and match the topic-subscription logic below. |
| docs/metrics.md | Adds the lean_attestation_committee_subnet row to the Network Metrics table with correct type, usage description, and supported status. |
Sequence Diagram
sequenceDiagram
participant Caller
participant build_swarm (lib.rs)
participant metrics.rs
participant Prometheus Registry
Caller->>build_swarm (lib.rs): build_swarm(config)
build_swarm (lib.rs)->>build_swarm (lib.rs): subnet_id = config.validator_id.map(|vid| vid % attestation_committee_count)
build_swarm (lib.rs)->>metrics.rs: set_attestation_committee_subnet(subnet_id.unwrap_or(0))
metrics.rs->>Prometheus Registry: LazyLock::new → register_int_gauge!("lean_attestation_committee_subnet") [once]
metrics.rs->>Prometheus Registry: LEAN_ATTESTATION_COMMITTEE_SUBNET.set(subnet_id as i64)
build_swarm (lib.rs)->>build_swarm (lib.rs): subscribe to attestation topic (validators only)
build_swarm (lib.rs)->>Caller: swarm
Prompt To Fix All With AI
This is a comment left during a code review.
Path: crates/net/p2p/src/metrics.rs
Line: 72-81
Comment:
**Function-scoped static inconsistent with file pattern**
The three existing metrics in this file (`LEAN_CONNECTED_PEERS`, `LEAN_PEER_CONNECTION_EVENTS_TOTAL`, `LEAN_PEER_DISCONNECTION_EVENTS_TOTAL`) all use module-level `LazyLock` statics, while this new gauge uses a function-scoped static. Both are valid Rust, but mixing them in the same file creates an inconsistency.
The PR description notes this follows the blockchain metrics module pattern, but it would be more consistent with the rest of `metrics.rs` to hoist the static to module scope:
```rust
static LEAN_ATTESTATION_COMMITTEE_SUBNET: LazyLock<IntGauge> = LazyLock::new(|| {
register_int_gauge!(
"lean_attestation_committee_subnet",
"Node's attestation committee subnet"
)
.unwrap()
});
/// Set the attestation committee subnet gauge.
pub fn set_attestation_committee_subnet(subnet_id: u64) {
LEAN_ATTESTATION_COMMITTEE_SUBNET.set(subnet_id.try_into().unwrap_or_default());
}
```
This aligns with how every other metric in this file is structured.
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: "Update crates/net/p2..."
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
|
@greptile-apps please review it again |
crates/net/p2p/src/lib.rs
Outdated
| let subnet_id = config | ||
| .validator_id | ||
| .map(|vid| vid % config.attestation_committee_count); | ||
| metrics::set_attestation_committee_subnet(subnet_id.unwrap_or(0)); |
There was a problem hiding this comment.
We should put this inside the config.is_aggregator if.
crates/net/p2p/src/lib.rs
Outdated
There was a problem hiding this comment.
This could be simplified to subnet_id.unwrap_or(0), like in the metric call
simplify subnet_id match, and use unwrap_or_default for try_into
…gators The leanMetrics spec defines this as "on node start" without a validator-only qualifier. Non-validators use subnet 0 for fanout publishing, so exposing 0 is accurate.
Motivation
The leanMetrics specification defines
lean_attestation_committee_subnetas a Network Metric (Gauge, set on node start) that all lean clients should expose. ethlambda already computes the subnet ID at startup (validator_id % attestation_committee_count) for gossipsub topic subscription, but does not expose it as a Prometheus gauge.This brings ethlambda closer to full leanMetrics compliance and helps operators verify subnet assignments via Grafana dashboards.
Description
Register a new
lean_attestation_committee_subnetPrometheusIntGaugein the P2P metrics module and set it at startup with the computed subnet ID.Changes
crates/net/p2p/src/metrics.rs: Newset_attestation_committee_subnet(subnet_id: u64)function with a function-scopedLazyLock<IntGauge>, following the same pattern used byset_attestation_committee_countin the blockchain metrics module.crates/net/p2p/src/lib.rs: Call the setter after computingsubnet_id(line 213), passingsubnet_id.unwrap_or(0). Non-validator nodes default to subnet 0, which matches their fanout publishing behavior.docs/metrics.md: Added row to the Network Metrics table documenting the new metric as supported.Design decisions
How to Test
To verify at runtime: start a node and check
curl http://localhost:5054/metrics | grep lean_attestation_committee_subnet.