consensus: backport abci and consensus metrics (#9273)

Partial backport of #8480
This commit is contained in:
William Banfield
2022-08-17 09:37:45 -04:00
committed by GitHub
parent 9993514893
commit 7bd86ec004
7 changed files with 114 additions and 1 deletions
+28
View File
@@ -162,6 +162,30 @@ func PrometheusMetrics(namespace string, labelsAndValues ...string) *Metrics {
Name: "full_prevote_delay",
Help: "Interval in seconds between the proposal timestamp and the timestamp of the latest prevote in a round where all validators voted.",
}, append(labels, "proposer_address")).With(labelsAndValues...),
ProposalReceiveCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: namespace,
Subsystem: MetricsSubsystem,
Name: "proposal_receive_count",
Help: "ProposalReceiveCount is the total number of proposals received by this node since process start. The metric is annotated by the status of the proposal from the application, either 'accepted' or 'rejected'.",
}, append(labels, "status")).With(labelsAndValues...),
ProposalCreateCount: prometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: namespace,
Subsystem: MetricsSubsystem,
Name: "proposal_create_count",
Help: "ProposalCreationCount is the total number of proposals created by this node since process start.",
}, labels).With(labelsAndValues...),
RoundVotingPowerPercent: prometheus.NewGaugeFrom(stdprometheus.GaugeOpts{
Namespace: namespace,
Subsystem: MetricsSubsystem,
Name: "round_voting_power_percent",
Help: "RoundVotingPowerPercent is the percentage of the total voting power received with a round. The value begins at 0 for each round and approaches 1.0 as additional voting power is observed. The metric is labeled by vote type.",
}, labels).With(labelsAndValues...),
LateVotes: prometheus.NewCounterFrom(stdprometheus.CounterOpts{
Namespace: namespace,
Subsystem: MetricsSubsystem,
Name: "late_votes",
Help: "LateVotes stores the number of votes that were received by this node that correspond to earlier heights and rounds than this node is currently in.",
}, labels).With(labelsAndValues...),
}
}
@@ -191,5 +215,9 @@ func NopMetrics() *Metrics {
BlockGossipPartsReceived: discard.NewCounter(),
QuorumPrevoteDelay: discard.NewGauge(),
FullPrevoteDelay: discard.NewGauge(),
ProposalReceiveCount: discard.NewCounter(),
ProposalCreateCount: discard.NewCounter(),
RoundVotingPowerPercent: discard.NewGauge(),
LateVotes: discard.NewCounter(),
}
}
+40
View File
@@ -6,6 +6,7 @@ import (
"github.com/go-kit/kit/metrics"
cstypes "github.com/tendermint/tendermint/consensus/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
"github.com/tendermint/tendermint/types"
)
@@ -92,6 +93,26 @@ type Metrics struct {
// of the voting power on the network issued prevotes.
//metrics:Interval in seconds between the proposal timestamp and the timestamp of the latest prevote in a round where all validators voted.
FullPrevoteDelay metrics.Gauge `metrics_labels:"proposer_address"`
// ProposalReceiveCount is the total number of proposals received by this node
// since process start.
// The metric is annotated by the status of the proposal from the application,
// either 'accepted' or 'rejected'.
ProposalReceiveCount metrics.Counter `metrics_labels:"status"`
// ProposalCreationCount is the total number of proposals created by this node
// since process start.
ProposalCreateCount metrics.Counter
// RoundVotingPowerPercent is the percentage of the total voting power received
// with a round. The value begins at 0 for each round and approaches 1.0 as
// additional voting power is observed. The metric is labeled by vote type.
RoundVotingPowerPercent metrics.Gauge
// LateVotes stores the number of votes that were received by this node that
// correspond to earlier heights and rounds than this node is currently
// in.
LateVotes metrics.Counter
}
// RecordConsMetrics uses for recording the block related metrics during fast-sync.
@@ -102,12 +123,31 @@ func (m *Metrics) RecordConsMetrics(block *types.Block) {
m.CommittedHeight.Set(float64(block.Height))
}
func (m *Metrics) MarkProposalProcessed(accepted bool) {
status := "accepted"
if !accepted {
status = "rejected"
}
m.ProposalReceiveCount.With("status", status).Add(1)
}
func (m *Metrics) MarkVoteReceived(vt tmproto.SignedMsgType, power, totalPower int64) {
p := float64(power) / float64(totalPower)
n := strings.ToLower(strings.TrimPrefix(vt.String(), "SIGNED_MSG_TYPE_"))
m.RoundVotingPowerPercent.With("vote_type", n).Add(p)
}
func (m *Metrics) MarkRound(r int32, st time.Time) {
m.Rounds.Set(float64(r))
roundTime := time.Since(st).Seconds()
m.RoundDurationSeconds.Observe(roundTime)
}
func (m *Metrics) MarkLateVote(vt tmproto.SignedMsgType) {
n := strings.ToLower(strings.TrimPrefix(vt.String(), "SIGNED_MSG_TYPE_"))
m.LateVotes.With("vote_type", n).Add(1)
}
func (m *Metrics) MarkStep(s cstypes.RoundStepType) {
if !m.stepStart.IsZero() {
stepTime := time.Since(m.stepStart).Seconds()
+11
View File
@@ -1144,6 +1144,7 @@ func (cs *State) defaultDecideProposal(height int64, round int32) {
} else if block == nil {
panic("Method createProposalBlock should not provide a nil block without errors")
}
cs.metrics.ProposalCreateCount.Add(1)
blockParts, err = block.MakePartSet(types.BlockPartSizeBytes)
if err != nil {
cs.Logger.Error("unable to create proposal block part set", "error", err)
@@ -1308,6 +1309,7 @@ func (cs *State) defaultDoPrevote(height int64, round int32) {
"state machine returned an error (%v) when calling ProcessProposal", err,
))
}
cs.metrics.MarkProposalProcessed(isAppValid)
// Vote nil if the Application rejected the block
if !isAppValid {
@@ -2051,6 +2053,10 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error
"cs_height", cs.Height,
)
if vote.Height < cs.Height || (vote.Height == cs.Height && vote.Round < cs.Round) {
cs.metrics.MarkLateVote(vote.Type)
}
// A precommit for the previous height?
// These come in while we wait timeoutCommit
if vote.Height+1 == cs.Height && vote.Type == tmproto.PrecommitType {
@@ -2095,6 +2101,11 @@ func (cs *State) addVote(vote *types.Vote, peerID p2p.ID) (added bool, err error
// Either duplicate, or error upon cs.Votes.AddByIndex()
return
}
if vote.Round == cs.Round {
vals := cs.state.Validators
_, val := vals.GetByIndex(vote.ValidatorIndex)
cs.metrics.MarkVoteReceived(vote.Type, val.VotingPower, vals.TotalVotingPower())
}
if err := cs.eventBus.PublishEventVote(types.EventDataVote{Vote: vote}); err != nil {
return added, err