Skip to content

Commit

Permalink
feat: add forkchoice data structures metrics (#5576)
Browse files Browse the repository at this point in the history
Add forkchoice data structures metrics

Co-authored-by: Cayman <[email protected]>
  • Loading branch information
dapplion and wemeetagain authored May 31, 2023
1 parent 3fe9afd commit 399687b
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 12 deletions.
32 changes: 21 additions & 11 deletions packages/beacon-node/src/chain/chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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 {
Expand Down
24 changes: 24 additions & 0 deletions packages/beacon-node/src/metrics/metrics/beacon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand Down
12 changes: 12 additions & 0 deletions packages/fork-choice/src/forkChoice/forkChoice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
EpochDifference,
AncestorResult,
AncestorStatus,
ForkChoiceMetrics,
} from "./interface.js";
import {IForkChoiceStore, CheckpointWithHex, toCheckpointWithHex, JustifiedBalances} from "./store.js";

Expand Down Expand Up @@ -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.)
Expand Down
11 changes: 11 additions & 0 deletions packages/fork-choice/src/forkChoice/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.)
Expand Down
9 changes: 8 additions & 1 deletion packages/fork-choice/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 399687b

Please sign in to comment.