consensus: calculate prevote message delay metric

This commit is contained in:
William Banfield
2022-01-10 18:27:00 -05:00
parent 90cf742065
commit 2bcc983aa3
3 changed files with 61 additions and 0 deletions

View File

@@ -64,6 +64,21 @@ type Metrics struct {
// Histogram of time taken per step annotated with reason that the step proceeded.
StepTime metrics.Histogram
// QuroumPrevoteMessageDelay is the difference in seconds between the proposal
// timestamp and the timestamp of the prevote that achieved a quorum in the prevote step.
// The prevote that achieved a quorum in the prevote step is determined by first
// sorting all of the collected prevotes in a round in ascending order of
// timestamp and iterating over this list from lowest timestamp to highest.
// During iteration, the total represented by iterated prevotes is kept track of.
// The prevote that achieved a quorum is the prevote that brings the summed
// voting power in this iteration to above 2/3 of the power on the network.
QuorumPrevoteMessageDelay metrics.Gauge
// FullPrevoteMessageDelay is the difference in seconds between the proposal
// timestamp and the timestamp of the prevote that achieved 100% of the voting
// power on the network in the prevote step when prevotes are ordered by timestamp.
FullPrevoteMessageDelay metrics.Gauge
}
// PrometheusMetrics returns Metrics build using Prometheus client library.
@@ -196,6 +211,20 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics {
Name: "step_time",
Help: "Time spent per step.",
}, append(labels, "step", "reason")).With(labelsAndValues...),
QuorumPrevoteMessageDelay: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: namespace,
Subsystem: MetricsSubsystem,
Name: "quorum_prevote_message_delay",
Help: "Difference in seconds between the proposal timestamp and the timestamp " +
"of the prevote that achieved a quorum in the prevote step.",
}, labels).With(labelsAndValues...),
FullPrevoteMessageDelay: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: namespace,
Subsystem: MetricsSubsystem,
Name: "complete_prevote_message_delay",
Help: "Difference in seconds between the proposal timestamp and the timestamp " +
"of the prevote that achieved 100% of the voting power in the prevote step.",
}, labels).With(labelsAndValues...),
}
}

View File

@@ -8,6 +8,7 @@ import (
"io"
"os"
"runtime/debug"
"sort"
"sync"
"time"
@@ -1680,6 +1681,8 @@ func (cs *State) finalizeCommit(ctx context.Context, height int64) {
return
}
cs.calculatePrevoteMessageDelayMetrics()
blockID, ok := cs.Votes.Precommits(cs.CommitRound).TwoThirdsMajority()
block, blockParts := cs.ProposalBlock, cs.ProposalBlockParts
@@ -2414,6 +2417,26 @@ func (cs *State) checkDoubleSigningRisk(height int64) error {
return nil
}
func (cs *State) calculatePrevoteMessageDelayMetrics() {
ps := cs.Votes.Prevotes(cs.Round)
pl := ps.List()
sort.Slice(pl, func(i, j int) bool {
return pl[i].Timestamp.Before(pl[j].Timestamp)
})
var votingPowerSeen int64
for _, v := range pl {
_, val := cs.Validators.GetByAddress(v.ValidatorAddress)
votingPowerSeen += val.VotingPower
if votingPowerSeen >= cs.Validators.TotalVotingPower()*(2/3+1) {
cs.metrics.QuorumPrevoteMessageDelay.Set(v.Timestamp.Sub(cs.Proposal.Timestamp).Seconds())
break
}
}
if ps.HasAll() {
cs.metrics.FullPrevoteMessageDelay.Set(pl[len(pl)-1].Timestamp.Sub(cs.Proposal.Timestamp).Seconds())
}
}
//---------------------------------------------------------
func CompareHRS(h1 int64, r1 int32, s1 cstypes.RoundStepType, h2 int64, r2 int32, s2 cstypes.RoundStepType) int {

View File

@@ -378,6 +378,15 @@ func (voteSet *VoteSet) GetByIndex(valIndex int32) *Vote {
return voteSet.votes[valIndex]
}
// List returns a copy of the list of votes stored by the VoteSet.
func (voteSet *VoteSet) List() []Vote {
votes := make([]Vote, len(voteSet.votes))
for i := range voteSet.votes {
votes[i] = *voteSet.votes[i]
}
return votes
}
func (voteSet *VoteSet) GetByAddress(address []byte) *Vote {
if voteSet == nil {
return nil