From 15dee9c700d2260bda7499e9236bb83e050e904f Mon Sep 17 00:00:00 2001 From: dapplion <35266934+dapplion@users.noreply.github.com> Date: Tue, 30 May 2023 10:11:12 +0300 Subject: [PATCH] Add forkchoice data structures metrics --- packages/beacon-node/src/chain/chain.ts | 32 ++++++++++++------- .../beacon-node/src/metrics/metrics/beacon.ts | 24 ++++++++++++++ .../fork-choice/src/forkChoice/forkChoice.ts | 12 +++++++ .../fork-choice/src/forkChoice/interface.ts | 11 +++++++ packages/fork-choice/src/index.ts | 9 +++++- 5 files changed, 76 insertions(+), 12 deletions(-) diff --git a/packages/beacon-node/src/chain/chain.ts b/packages/beacon-node/src/chain/chain.ts index b5e360616fa9..93c1bcbb58d3 100644 --- a/packages/beacon-node/src/chain/chain.ts +++ b/packages/beacon-node/src/chain/chain.ts @@ -284,7 +284,9 @@ export class BeaconChain implements IBeaconChain { new PrepareNextSlotScheduler(this, this.config, metrics, this.logger, signal); } - metrics?.opPool.aggregatedAttestationPoolSize.addCollect(() => this.onScrapeMetrics()); + if (metrics) { + metrics.opPool.aggregatedAttestationPoolSize.addCollect(() => this.onScrapeMetrics(metrics)); + } // Event handlers. emitter is created internally and dropped on close(). Not need to .removeListener() clock.addListener(ClockEvent.slot, this.onClockSlot.bind(this)); @@ -652,17 +654,25 @@ export class BeaconChain implements IBeaconChain { this.logger.debug("Persisted invalid ssz object", {id: suffix, filepath}); } - private onScrapeMetrics(): void { + private onScrapeMetrics(metrics: Metrics): void { const {attestationCount, attestationDataCount} = this.aggregatedAttestationPool.getAttestationCount(); - this.metrics?.opPool.aggregatedAttestationPoolSize.set(attestationCount); - this.metrics?.opPool.aggregatedAttestationPoolUniqueData.set(attestationDataCount); - this.metrics?.opPool.attestationPoolSize.set(this.attestationPool.getAttestationCount()); - this.metrics?.opPool.attesterSlashingPoolSize.set(this.opPool.attesterSlashingsSize); - this.metrics?.opPool.proposerSlashingPoolSize.set(this.opPool.proposerSlashingsSize); - this.metrics?.opPool.voluntaryExitPoolSize.set(this.opPool.voluntaryExitsSize); - this.metrics?.opPool.syncCommitteeMessagePoolSize.set(this.syncCommitteeMessagePool.size); - this.metrics?.opPool.syncContributionAndProofPoolSize.set(this.syncContributionAndProofPool.size); - this.metrics?.opPool.blsToExecutionChangePoolSize.set(this.opPool.blsToExecutionChangeSize); + metrics.opPool.aggregatedAttestationPoolSize.set(attestationCount); + metrics.opPool.aggregatedAttestationPoolUniqueData.set(attestationDataCount); + metrics.opPool.attestationPoolSize.set(this.attestationPool.getAttestationCount()); + metrics.opPool.attesterSlashingPoolSize.set(this.opPool.attesterSlashingsSize); + metrics.opPool.proposerSlashingPoolSize.set(this.opPool.proposerSlashingsSize); + metrics.opPool.voluntaryExitPoolSize.set(this.opPool.voluntaryExitsSize); + metrics.opPool.syncCommitteeMessagePoolSize.set(this.syncCommitteeMessagePool.size); + metrics.opPool.syncContributionAndProofPoolSize.set(this.syncContributionAndProofPool.size); + metrics.opPool.blsToExecutionChangePoolSize.set(this.opPool.blsToExecutionChangeSize); + + const forkChoiceMetrics = this.forkChoice.getMetrics(); + metrics.forkChoice.votes.set(forkChoiceMetrics.votes); + metrics.forkChoice.queuedAttestations.set(forkChoiceMetrics.queuedAttestations); + metrics.forkChoice.validatedAttestationDatas.set(forkChoiceMetrics.validatedAttestationDatas); + metrics.forkChoice.balancesLength.set(forkChoiceMetrics.balancesLength); + metrics.forkChoice.nodes.set(forkChoiceMetrics.nodes); + metrics.forkChoice.indices.set(forkChoiceMetrics.indices); } private onClockSlot(slot: Slot): void { diff --git a/packages/beacon-node/src/metrics/metrics/beacon.ts b/packages/beacon-node/src/metrics/metrics/beacon.ts index 4c68c4d1b15a..25f842e635af 100644 --- a/packages/beacon-node/src/metrics/metrics/beacon.ts +++ b/packages/beacon-node/src/metrics/metrics/beacon.ts @@ -83,6 +83,30 @@ export function createBeaconMetrics(register: RegistryMetricCreator) { // Add buckets up to 100 to capture high depth re-orgs. Above 100 things are going really bad. buckets: [1, 2, 3, 5, 7, 10, 20, 30, 50, 100], }), + votes: register.gauge({ + name: "beacon_fork_choice_votes_count", + help: "Current count of votes in fork choice data structures", + }), + queuedAttestations: register.gauge({ + name: "beacon_fork_choice_queued_attestations_count", + help: "Current count of queued_attestations in fork choice data structures", + }), + validatedAttestationDatas: register.gauge({ + name: "beacon_fork_choice_validated_attestation_datas_count", + help: "Current count of validatedAttestationDatas in fork choice data structures", + }), + balancesLength: register.gauge({ + name: "beacon_fork_choice_balances_length", + help: "Current length of balances in fork choice data structures", + }), + nodes: register.gauge({ + name: "beacon_fork_choice_nodes_count", + help: "Current count of nodes in fork choice data structures", + }), + indices: register.gauge({ + name: "beacon_fork_choice_indices_count", + help: "Current count of indices in fork choice data structures", + }), }, parentBlockDistance: register.histogram({ diff --git a/packages/fork-choice/src/forkChoice/forkChoice.ts b/packages/fork-choice/src/forkChoice/forkChoice.ts index a354846bfb68..082e74b86561 100644 --- a/packages/fork-choice/src/forkChoice/forkChoice.ts +++ b/packages/fork-choice/src/forkChoice/forkChoice.ts @@ -39,6 +39,7 @@ import { EpochDifference, AncestorResult, AncestorStatus, + ForkChoiceMetrics, } from "./interface.js"; import {IForkChoiceStore, CheckpointWithHex, toCheckpointWithHex, JustifiedBalances} from "./store.js"; @@ -112,6 +113,17 @@ export class ForkChoice implements IForkChoice { this.balances = this.fcStore.justified.balances; } + getMetrics(): ForkChoiceMetrics { + return { + votes: this.votes.length, + queuedAttestations: this.queuedAttestations.size, + validatedAttestationDatas: this.validatedAttestationDatas.size, + balancesLength: this.balances.length, + nodes: this.protoArray.nodes.length, + indices: this.protoArray.indices.size, + }; + } + /** * Returns the block root of an ancestor of `blockRoot` at the given `slot`. * (Note: `slot` refers to the block that is *returned*, not the one that is supplied.) diff --git a/packages/fork-choice/src/forkChoice/interface.ts b/packages/fork-choice/src/forkChoice/interface.ts index 73780687ca72..885c4c0b071a 100644 --- a/packages/fork-choice/src/forkChoice/interface.ts +++ b/packages/fork-choice/src/forkChoice/interface.ts @@ -37,8 +37,19 @@ export type AncestorResult = | {code: AncestorStatus.NoCommonAncenstor} | {code: AncestorStatus.BlockUnknown}; +export type ForkChoiceMetrics = { + votes: number; + queuedAttestations: number; + validatedAttestationDatas: number; + balancesLength: number; + nodes: number; + indices: number; +}; + export interface IForkChoice { irrecoverableError?: Error; + + getMetrics(): ForkChoiceMetrics; /** * Returns the block root of an ancestor of `block_root` at the given `slot`. (Note: `slot` refers * to the block that is *returned*, not the one that is supplied.) diff --git a/packages/fork-choice/src/index.ts b/packages/fork-choice/src/index.ts index 87b1fa183b53..922e624bae97 100644 --- a/packages/fork-choice/src/index.ts +++ b/packages/fork-choice/src/index.ts @@ -10,7 +10,14 @@ export { } from "./protoArray/interface.js"; export {ForkChoice, ForkChoiceOpts, assertValidTerminalPowBlock} from "./forkChoice/forkChoice.js"; -export {IForkChoice, PowBlockHex, EpochDifference, AncestorResult, AncestorStatus} from "./forkChoice/interface.js"; +export { + IForkChoice, + PowBlockHex, + EpochDifference, + AncestorResult, + AncestorStatus, + ForkChoiceMetrics, +} from "./forkChoice/interface.js"; export {ForkChoiceStore, IForkChoiceStore, CheckpointWithHex, JustifiedBalancesGetter} from "./forkChoice/store.js"; export { InvalidAttestation,